显然,关注点分离是我们代码中的理想特征,大多数人采取的第一个明显步骤是将数据访问与表示分开。在我的情况下,LINQ To SQL正在数据访问对象中用于数据访问。
我的问题是,实体对象的使用应该停在哪里?为了澄清,我可以将实体对象传递到域层,但我觉得实体对象不仅仅是一个数据对象 - 就像将DAL的一部分传递到下一层一样。
假设我有一个UserDAL类,它应该在调用方法GetByID()时将实体User对象暴露给域,还是应该纯粹用于存储数据的纯数据对象? (在这种情况下似乎浪费重复)
你们在同样的情况下做了什么?有替代方法吗?
希望不是太模糊。
非常感谢,
马丁。
我从我的DAL(使用LINQ2SQL)返回POCO的IQueryable,因此没有Linq实体对象离开DAL。这些POCO返回到服务和UI层,还用于将数据传递回DAL进行处理。 Linq处理得非常好:
IQueryable<MyObjects.Product> products = from p in linqDataContext.Products
select new MyObjects.Product //POCO
{
ProductID = p.ProductID
};
return products;
我从我的DAL(使用LINQ2SQL)返回POCO的IQueryable,因此没有Linq实体对象离开DAL。这些POCO返回到服务和UI层,还用于将数据传递回DAL进行处理。 Linq处理得非常好:
IQueryable<MyObjects.Product> products = from p in linqDataContext.Products
select new MyObjects.Product //POCO
{
ProductID = p.ProductID
};
return products;
对于大多数项目,我们使用LINQ to SQL实体作为业务对象。
LINQ to SQL设计器允许您控制它生成的类和属性的可访问性,因此您可以限制对允许使用者违反业务规则的任何内容的访问,并提供适当的公共备选方案(尊重业务规则)部分课程。
甚至还有一篇文章 实现您的业务逻辑 这种方式在MSDN上。
这样可以避免编写 批量 繁琐的样板代码,你甚至可以 使您的实体可序列化 如果要从Web服务返回它们。
是否为业务逻辑创建单独的层实际上取决于项目的大小(较大的项目通常在业务逻辑和数据访问层之间具有更大的差异)。
我相信LINQ to Entities试图通过维护两个独立的模型来为这个难题提供一站式解决方案(a 概念架构 为您的业务逻辑和 存储架构 为您的数据访问)。
我个人不喜欢我的实体跨层传播。我的DAL返回POCO(当然,它通常意味着额外的工作,但我发现这更清洁 - 也许这将在下一个.NET版本中更简单;-))。
问题并不那么简单,对这个问题有很多不同的想法(我一直在问自己同样的问题)。
也许你可以看看 MVC店面示例应用程序 :我喜欢这个概念的本质(特别是在数据层中发生的映射)。
希望这可以帮助。
有一个类似的帖子 这里但是,我看到你的问题更多的是关于你应该做什么,而不是你应该怎么做。
在小型应用程序中,我发现第二个POCO实现是浪费的,在较大的应用程序(特别是那些实现Web服务的应用程序)中,POCO对象(通常是数据传输对象)很有用。
如果您的应用属于后一种情况,您可能需要查看 ADO.Net数据服务。
希望有所帮助!
我实际上也在努力解决这个问题。使用普通的LINQ to SQL,我很快放弃了DBML工具,因为它将实体绑定到DAL。虽然微软并没有让它变得非常容易,但我仍在努力争取更高水平的持久性无知。
我最终做的是通过让DAL继承自我的POCO来手写持久性无知层。继承的对象暴露了它继承的POCO的相同属性,因此在持久性无知层内部,我可以使用属性映射到对象。然后,被调用者可以将继承的对象强制转换回其基类型,或让DAL为它们执行此操作。我更喜欢后一种情况,因为它减少了需要完成的铸造量。当然,这是一个主要的只读实现,因此我不得不重新审视它以获得更复杂的更新方案。
手动编码的数量相当大,因为我还必须在对象继承和映射之上手动维护(在编码之后,开始时)每个数据源的上下文和提供程序。如果这个项目被弃用,我肯定会转向更强大的解决方案。
期待实体框架,根据EF团队的设计博客,持久性无知是一个常见的功能。与此同时,如果您决定使用EF路线,您可以随时查看预先滚动的持久性无知工具,例如 EFPocoAdapter 在MSDN上的项目,以帮助。
我使用一个自定义的LinqToSQL生成器,它基于我在Internet上找到的生成器,代替默认的MSLinqToSQLGenerator。
为了使我的上层独立于这样的Linq对象,我创建接口来表示它们中的每一个,然后在这些层中使用这些接口。
例:
public interface IConcept {
long Code { get; set; }
string Name { get; set; }
bool IsDefault { get; set; }
}
public partial class Concept : IConcept { }
[Table(Name="dbo.Concepts")]
public partial class Concept
{
private long _Code;
private string _Name;
private bool _IsDefault;
partial void OnCreated();
public Concept() { OnCreated(); }
[Column(Storage="_Code", DbType="BigInt NOT NULL IDENTITY", IsPrimaryKey=true)]
public long Code
{
//***
}
[Column(Storage="_Name", DbType="VarChar(50) NOT NULL")]
public string Name
{
//***
}
[Column(Storage="_IsDefault", DbType="Bit NOT NULL")]
public bool IsDefault
{
//***
}
}
当然还有更多,但这就是主意。
请记住,Linq to SQL不是一种前瞻性技术。它被发布了,玩起来很有趣,但微软并没有把它带到任何地方。我感觉它也不会永远得到支持。看一下Microsoft的实体框架(EF),它结合了Linq to SQL的一些优点。