【问题标题】:LINQ To SQL entity objects as domain objectsLINQ To SQL 实体对象作为域对象
【发布时间】:2010-09-22 20:58:34
【问题描述】:

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

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

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

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

希望这不是太模糊。

非常感谢,

马丁。

【问题讨论】:

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


    【解决方案1】:

    我从我的 DAL(使用 LINQ2SQL)返回 IQueryable 的 POCO,因此没有任何 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;
    

    【讨论】:

    • 您如何处理来自服务层的更新,因为该层(我猜)使用您的 POCO?假设您像这样更新了产品名称: MyObjects.Product product = from p in linqDataContext.Products where p.ID = 1 select new MyObjects.Product //POCO { ProductID = p.ProductID, ProductName = p.ProductName }; product.Name = "新名称";现在,你如何更新?
    【解决方案2】:

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

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

    也许你可以看看MVC Storefront sample app:我喜欢这个概念的本质(尤其是数据层中发生的映射)。

    希望这会有所帮助。

    【讨论】:

      【解决方案3】:

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

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

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

      希望有帮助!

      【讨论】:

        【解决方案4】:

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

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

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

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

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

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

        【讨论】:

          【解决方案5】:

          实际上,我也为此苦苦挣扎。使用普通的 LINQ to SQL,我很快放弃了 DBML 工具,因为它将实体紧密地绑定到 DAL。我一直在努力争取更高水平的持久性无知,尽管微软并没有让它变得很容易。

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

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

          期待 Entity Framework,根据 EF 团队的设计博客,持久性无知是一个普遍要求的功能。同时,如果您决定走 EF 路线,您可以随时查看预先推出的持久性无知工具,例如 MSDN 上的 EFPocoAdapter 项目,以提供帮助。

          【讨论】:

            【解决方案6】:

            我使用基于我在 Internet 上找到的自定义 LinqToSQL 生成器来代替默认的 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
                {
                         //***
                }
            }
            

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

            【讨论】:

              【解决方案7】:

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

              【讨论】:

                猜你喜欢
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 2011-10-22
                • 2011-03-06
                • 1970-01-01
                • 1970-01-01
                • 2013-09-11
                • 1970-01-01
                相关资源
                最近更新 更多