Классы сущностей отделены от поставщика LINQ to SQL для реализации шаблона Repository. Как?
-
04-07-2019 - |
Вопрос
Я просмотрел шаблон репозитория и узнал некоторые идеи, которые я использовал в прошлом, которые заставили меня чувствовать себя хорошо.
Однако теперь я хотел бы написать приложение, которое использовало бы этот шаблон , но мне бы хотелось, чтобы откалиброванные классы объектов были предоставлены поставщиком хранилища.
Я бы создал несколько сборок:
<Ол>Изучение 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 а> р>
Я думаю, что вам нужна поддержка POCO (Plain Old CLR Objects). LINQ to SQL имеет адаптер под названием Close2Poco .
Но я бы посоветовал перейти на Entity Framework, так как на данный момент у них также есть адаптер POCO , но в v2 ожидается, что он будет поддерживаться" из коробки ".
Вам не нужно использовать сгенерированный код 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 и т. Д.) И интерфейсы " Интерфейсы " сборка отделена от других сборок, связанных с реализацией.