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


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

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

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

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

希望不是太模糊。

非常感谢,

马丁。


9692
2017-11-18 14:58


起源



答案:


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

5
2017-11-18 15:12



你如何处理服务层的更新,因为那层(我猜)使用你的POCO?假设您更新了产品名称,如下所示:MyObjects.Product product = from p in linqDataContext.Products其中p.ID = 1选择new MyObjects.Product // POCO {ProductID = p.ProductID,ProductName = p.ProductName}; product.Name =“新名称”;现在,你如何更新? - Mustafakidd


答案:


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

5
2017-11-18 15:12



你如何处理服务层的更新,因为那层(我猜)使用你的POCO?假设您更新了产品名称,如下所示:MyObjects.Product product = from p in linqDataContext.Products其中p.ID = 1选择new MyObjects.Product // POCO {ProductID = p.ProductID,ProductName = p.ProductName}; product.Name =“新名称”;现在,你如何更新? - Mustafakidd


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

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

甚至还有一篇文章 实现您的业务逻辑 这种方式在MSDN上。

这样可以避免编写 批量 繁琐的样板代码,你甚至可以 使您的实体可序列化 如果要从Web服务返回它们。

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

我相信LINQ to Entities试图通过维护两个独立的模型来为这个难题提供一站式解决方案(a 概念架构 为您的业务逻辑和 存储架构 为您的数据访问)。


3
2017-11-24 14:58





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

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

也许你可以看看 MVC店面示例应用程序 :我喜欢这个概念的本质(特别是在数据层中发生的映射)。

希望这可以帮助。


1
2017-11-18 15:13





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

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

如果您的应用属于后一种情况,您可能需要查看 ADO.Net数据服务

希望有所帮助!


1
2017-11-18 15:16





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

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

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

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


0
2017-11-24 15:10





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

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


0
2017-11-26 19:42





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


0
2017-11-26 19:50