实体类与LINQ to SQL提供程序分离,用于实现Repository模式。怎么样?
-
04-07-2019 - |
题
我已经查看了存储库模式,并且我认识到我过去使用过的一些让我感觉良好的想法。
但是现在我想编写一个应用程序来使用这种模式但我想要从存储库提供程序中解析出来的 。
我会创建几个程序集:
- an“Interfaces”将托管包括IRepository接口在内的通用接口的程序集
- an“Entities”将托管实体类(如Product,User,Order等)的程序集。该组件将由“接口”引用。汇编,因为某些方法会返回它们的类型或数组。它也将由主应用程序集(例如Web应用程序) 引用
- 一个或多个存储库提供程序程序集/程序集。每个都包含(至少)一个实现IRepository接口的类,它可以与某个Data Store一起使用。数据存储可以包括SQL Server,Oracle服务器,MySQL,XML文件,Web / WCF服务等。 醇>
在我发现生成的类和CustomDataContext类之间的深度依赖关系之前,研究LINQ to SQL看起来非常有效,在实现所有的时间方面似乎很有效。
如何在这种情况下使用LINQ to SQL?
解决方案
我不知道这是不是你想要的,但你可能想看看Rob Conery的MVC店面代码。他使用linq提供程序的存储库模式的变体。他将LINQ to Sql对象映射到域对象,然后将域对象从存储库提供程序返回到服务层,该服务层包装提供程序,允许他在返回到业务层之前返回的数据上使用某些逻辑。
对我而言,您似乎希望提供程序返回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(普通旧CLR对象)支持。 LINQ to SQL有一个名为 Close2Poco 的适配器。
但我建议切换到实体框架,目前他们还有 POCO适配器,但在 v2预计将支持开箱即用。
您不必使用LINQ to SQL生成的代码,您可以使用必要的ColumnAttributes装饰自己的类或使用外部XML映射文件。
最简单的方法是将您的实体与datacontext分离:加载所需的实体,将其与DataContext分离,然后根据需要使用它,稍后使用Attach()将其与DataContext耦合以进行保存。
可悲的是,LINQ没有方法可以将实体从datacontext中解耦,但是你可以克隆它们,这很有效。最简单的方法是这样的:
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文件的自定义工具将生成OO模型。我的方法是在场景后面使用LINQ to SQL,因为我自动生成代码,所以很容易使用另一种机制让我们说MySQL数据源。由于LINQ to SQL不支持它,因此您必须手动编写数据访问代码,但使用OO模型的客户端代码将以任何方式更改。
您的Entity类是否可以实现将在“接口”中声明的IProduct,IUser,IOrder等接口。部件?这样,IRepository接口仅引用业务对象接口(即,返回IP产品等的集合)和“接口”接口。程序集与其他特定于实现的程序集分离。