Классы сущностей отделены от поставщика LINQ to SQL для реализации шаблона Repository. Как?

StackOverflow https://stackoverflow.com/questions/229627

Вопрос

Я просмотрел шаблон репозитория и узнал некоторые идеи, которые я использовал в прошлом, которые заставили меня чувствовать себя хорошо.

Однако теперь я хотел бы написать приложение, которое использовало бы этот шаблон , но мне бы хотелось, чтобы откалиброванные классы объектов были предоставлены поставщиком хранилища.

Я бы создал несколько сборок:

<Ол>
  • " Интерфейсы " сборка, которая будет содержать общие интерфейсы, включая интерфейс IRepository
  • " Сущности " сборка, которая будет содержать классы сущностей, такие как Product, User, Order и так далее. На эту сборку будет ссылаться " Интерфейсы " сборка, так как некоторые методы будут возвращать такие типы или массивы из них. Также на него будет ссылаться основная сборка приложения (например, веб-приложение)
  • одна или несколько сборок / сборок поставщика репозитория. Каждый из них будет включать (по крайней мере) класс, который реализует интерфейс IRepository, и он будет работать с определенным хранилищем данных. Хранилища данных могут включать SQL Server, сервер Oracle, MySQL, файлы XML, службы Web / WCF и т. Д.
  • Изучение LINQ to SQL, которое выглядит очень продуктивно с точки зрения времени, затрачиваемого на реализацию всего, кажется хорошим, пока я не обнаружу глубокую зависимость между сгенерированными классами и классом CustomDataContext.

    Как я могу использовать LINQ to SQL в таком сценарии?

    Это было полезно?

    Решение

    Я не знаю, является ли это именно тем, что вам нужно, но вы можете взглянуть на код магазина MVC Роба Конери. Он использует вариант шаблона хранилища с поставщиком linq. Он сопоставляет объекты LINQ to Sql с объектами домена, а затем возвращает объекты домена от поставщика репозитория на сервисный уровень, который оборачивает поставщика, позволяя ему проработать некоторую логику с данными, возвращаемыми до того, как они попадут на бизнес-уровень.

    Веб-трансляции с использованием MVC Storefront
    код

    Для меня это звучит так, как будто вы хотите, чтобы провайдеры возвращали DTO, а затем вы хотите сопоставить DTO с объектами домена на уровне хранилища / службы. В этом случае вы можете сопоставить ваш поставщик LINQ to SQL с DTO, сделать так, чтобы он возвращал их, а затем сопоставить DTO с объектами домена на уровне хранилища / службы. Это должно работать просто отлично, но это может стать утомительным, так как теперь у вас будет 2 слоя отображения.

    В этом случае у вас будет: ProductService, который принимает IProductRepository. Он вызывает методы в IProductRepository для возврата ваших DTO. Затем он сопоставляет DTO с реальными бизнес-объектами и возвращает их в вызывающий код.

    Другие советы

    Вы можете создать внешний XML-файл, сопоставляющий базу данных с любым классом:

     <?xml version="1.0" encoding="utf-8"?>
     <Database Name="DbName" 
               xmlns="http://schemas.microsoft.com/linqtosql/dbml/2007">
        <Table Name="DbTableName">
           <Type Name="EntityClassName" >
               <Column Name="ID" Type="System.Int64" Member="Id"
                       DbType="BigInt NOT NULL IDENTITY" IsPrimaryKey="true"
                       CanBeNull="false" />
               <Column Name="ColumnName" Type="System.String" Member="PropertyA"
                       DbType="VarChar(1024)" CanBeNull="true" />
           </Type>
        </Table>
     </Database>
    

    А затем передайте XML в класс DataContext:

     using (var cn = GetDbConnection())
      { var mappingSrc = XmlMappingSource.FromReader(xmlReader);
    
        using (var db = new DataContext(cn, mappingSrc))
         { var q = from entity in db.GetTable<EntityClassName>()
                   where entity.PropertyA = "..."
                   select entity.ID;
         }
      }
    

    Я нашел фантастическое сообщение в блоге (с большим количеством хорошего кода) об этом здесь: http://iridescence.no/post/Linq-to-Sql-Programming-Against-an-Interface-and-the-Repository-Pattern.aspx

    Вам не нужно использовать сгенерированный код LINQ to SQL, вы можете украсить свои собственные классы необходимыми ColumnAttributes или использовать внешний файл сопоставления XML.

    Простейшим способом было бы отделить ваши сущности от datacontext: загрузить нужную сущность, отделить ее от DataContext, использовать ее по своему усмотрению, позже использовать Attach (), чтобы связать ее с DataContext для сохранения.

    К сожалению, у LINQ нет метода, позволяющего отделить сущности от текста данных, но вы можете просто их клонировать, что прекрасно работает. Проще всего было бы что-то вроде этого:

    public static T CloneEntity<T>(T source)
    {
      DataContractSerializer dcs = new DataContractSerializer(typeof(T));
      using (Stream stream = new MemoryStream())
      {
        dcs.WriteObject(stream, source);
        stream.Seek(0, SeekOrigin.Begin);
        return (T)dcs.ReadObject(stream);
      }
    }
    

    Я сделал нечто подобное с WCF

    1 В вашем DBML установите режим сериализации на однонаправленный

    2 Установите ВСЕ столбцы в ваших таблицах на UpdateCheck = false

    3 Напишите свой сервис примерно так:

    <код>

       public class Service1 : IService1
        {
            public Company GetCompany(int companyId)
            {
                using (DataClasses1DataContext dc = new DataClasses1DataContext())
                {
                    return (from c in dc.Companies where c.CompanyId == companyId select c).Single();
                }
            }

        public void SaveCompany(Company company)
        {
            using (DataClasses1DataContext dc = new DataClasses1DataContext())
            {
                dc.Companies.Attach(company, true);
                dc.SubmitChanges();
            }
        }
    
        public void InsertCompany(Company company)
        {
            using (DataClasses1DataContext dc = new DataClasses1DataContext())
            {
                dc.Companies.InsertOnSubmit(company);
                dc.SubmitChanges();
            }
        }
    }
    

    4 Добавить сервисную ссылку

    Не совсем тот же сценарий, но я работаю над созданием специального инструмента, который на основе XML-файла будет генерировать ОО-модель. Мой подход заключается в использовании LINQ to SQL за кулисами, и, поскольку я генерирую код автоматически, было бы легко использовать другой механизм, скажем, для источника данных MySQL. Поскольку это не поддерживается LINQ to SQL, вам придется писать код доступа к данным вручную, но код клиента, который будет использовать модель OO, изменится любым образом.

    Могут ли ваши классы сущностей реализовать интерфейсы IProduct, IUser, IOrder и т. д., которые будут объявлены в ваших " Интерфейсах " сборка? Таким образом, интерфейс IRepository ссылается только на интерфейсы бизнес-объектов (т. Е. Возвращает коллекции IProduct и т. Д.) И интерфейсы " Интерфейсы " сборка отделена от других сборок, связанных с реализацией.

    Лицензировано под: CC-BY-SA с атрибуция
    Не связан с StackOverflow
    scroll top