LINQ To SQL实体对象作为域对象

时间:2008-11-18 14:58:31

标签: linq linq-to-sql dns data-access

显然,关注点分离是我们代码中的理想特征,大多数人采取的第一个明显步骤是将数据访问与表示分开。在我的情况下,LINQ To SQL正在数据访问对象中用于数据访问。

我的问题是,实体对象的使用应该停在哪里?为了澄清,我可以将实体对象传递到域层,但我觉得实体对象不仅仅是一个数据对象 - 就像将DAL的一部分传递到下一层一样。

假设我有一个UserDAL类,它应该在调用方法GetByID()时将实体User对象暴露给域,还是应该纯粹用于存储数据的纯数据对象? (在这种情况下似乎浪费重复)

你们在同样的情况下做了什么?有替代方法吗?

希望这不是太模糊。

非常感谢,

马丁。

7 个答案:

答案 0 :(得分:5)

我从我的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;

答案 1 :(得分:3)

对于大多数项目,我们使用LINQ to SQL实体作为业务对象。

LINQ to SQL设计器允许您控制其生成的类和属性的可访问性,因此您可以限制对允许使用者违反业务规则并提供合适的公共替代方案(尊重业务)的任何内容的访问权限部分类中的规则。

在MSDN上甚至有一篇关于implementing your business logic的文章。

这使您免于编写繁琐的样板代码的批次,如果您想从Web服务返回它们,您甚至可以make your entities serialisable

是否为业务逻辑创建单独的层实际上取决于项目的大小(较大的项目通常在业务逻辑和数据访问层之间具有更大的差异)。

我相信LINQ to Entities尝试通过维护两个独立的模型(一个conceptual schema用于您的业务逻辑,一个storage schema用于您的数据访问)来为这个难题提供一站式解决方案。

答案 2 :(得分:1)

我个人不喜欢我的实体在各个层面上传播。我的DAL返回POCO(当然,它通常意味着额外的工作,但我发现它更清洁 - 也许这在下一个.NET版本中会更简单; - ))。

问题不是那么简单,对这个问题有很多不同的想法(我一直在问自己同样的问题)。

也许你可以看看MVC Storefront sample app:我喜欢这个概念的本质(特别是在数据层中出现的映射)。

希望这有帮助。

答案 3 :(得分:1)

有一个类似的帖子here,但是,我看到你的问题更多的是你应该做什么,而不是你应该怎么做。

在小型应用程序中,我发现第二个POCO实现是浪费的,在较大的应用程序(特别是那些实现Web服务的应用程序)中,POCO对象(通常是数据传输对象)很有用。

如果您的应用属于后一种情况,您可能需要查看ADO.Net Data Services

希望有所帮助!

答案 4 :(得分:0)

我实际上也在努力解决这个问题。使用普通的LINQ to SQL,我很快放弃了DBML工具,因为它将实体绑定到DAL。尽管微软并没有让它变得非常容易,但我仍在努力争取更高水平的持久性无知。

我最终做的是通过让DAL继承自我的POCO来手写持久性无知层。继承的对象暴露了它继承的POCO的相同属性,因此在持久性无知层内部,我可以使用属性映射到对象。然后,被调用者可以将继承的对象强制转换回其基类型,或让DAL为它们执行此操作。我更喜欢后一种情况,因为它减少了需要完成的铸造量。当然,这是一个主要的只读实现,所以我不得不重新审视更复杂的更新场景。

对此的手动编码量相当大,因为我还必须在对象继承和映射之上手动维护(在编码之后,开始)每个数据源的上下文和提供程序。如果这个项目被弃用,我肯定会转向更强大的解决方案。

期待实体框架,根据EF团队的设计博客,持久性无知是一个常见的功能。与此同时,如果您决定使用EF路线,您可以随时查看预先推出的持久性无知工具,例如MSDN上的EFPocoAdapter项目,以提供帮助。

答案 5 :(得分:0)

我使用自定义的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
    {
             //***
    }
}

当然还有更多,但这就是主意。

答案 6 :(得分:0)

请记住,Linq to SQL不是一种前瞻性技术。它被发布了,玩起来很有趣,但微软并没有把它带到任何地方。我有一种感觉它也不会永远得到支持。看一下Microsoft的实体框架(EF),它结合了Linq to SQL的一些优点。