【问题标题】:Problems with EF-Agnostic design consumed by WCF service.WCF 服务使用的与 EF 无关的设计问题。
【发布时间】:2012-10-03 20:59:01
【问题描述】:

我正在尝试设置 EF 以在 WCF 上工作并保持域类模型 EF 不可知。

代码被组织成 3 个项目。 (我正在尝试 DDD - 我对它很陌生,但期待学习更多)

项目:QA - 领域层。包含 DataContract 模型/实体。 参考 QA.数据 项目:QA.Data - 数据层。包含上下文和 EDMX(代码生成策略 = "none") 参考 实体框架/System.Data.Entity 项目:QA.Repository - 数据访问/存储库。包含存储库类 参考 QA [领域层] QA.Data [数据层] 实体框架/System.DataEntity

我的理解是领域层可以引用数据层,但数据层不应该引用领域。这提出的问题是我的域模型/类是在域层中定义的,但创建和返回它们的上下文是在数据层中。为了让我的上下文知道返回一个“Widget”对象,它需要一个对定义“Widget”的域层的引用

我的(失败的)解决方案:我的解决方案是为每个领域模型创建接口并将它们放置在数据层中。上下文将返回... IdbSet ...这些接口又将由域模型实现,因此使我的数据层无需直接引用我的域(这无论如何都会导致非法循环引用)。域模型最初是使用“ADO.NET DbContext Generator w/WCF Support”T4 模板构建的。此过程导致在小部件类定义的开头包含 [KnownType(typeof(IWidgetPiece))]。 (一个 Widget 有一个导航属性 ...ICollection ...)

当我尝试访问服务时出现问题,我收到以下错误

'QA.Data.IWidgetPiece' 无法添加到已知类型列表,因为 具有相同数据合同名称的另一种类型“System.Object” 'http://www.w3.org/2001/XMLSchema:anyType' 已经存在。如果 有特定类型的不同集合 - 例如, List 和 Test[],它们不能同时添加为已知类型。 考虑仅指定其中一种类型以添加​​到已知的 类型列表。

我可以将这些更改为具体的实现... [KnownType(typeof(WidgetPiece))] ...但我继续收到此错误,因为它们所指的导航属性仍在返回它的 IWidgetPiece 接口类型必须这样做才能满足接口实现。

我正在试图弄清楚如何将事情适当地分开,并且仍然让上下文返回它应该返回的内容。由于这个和其他原因,返回接口的上下文仍然不能与我“坐在一起”,但我想不出另一种方法来做到这一点,即使这也提出了上述问题。帮助!

一些代码希望能澄清我之前的胡言乱语...

namespace QA.Data
{

    public interface IWidgetPiece
    {
        String ID { get; set; }
    }

    public interface IWidget
    {
        String ID { get; set; }
        ICollection<IWidgetPiece> Pieces;    
    }

    public partial class WidgetEntities : DbContext
    {
        IDbSet<IWidget> Widgets { get; set; }
        IDbSet<IWidgetPiece> WidgetPieces { get; set; }
    }

}


namespace QA
{
    [KnownType(typeof(IWidgetPiece))]
//  [KnownType(typeof(WidgetPiece))]
    [DataContract(IsReference = true)]
    public partial class Widget : QA.Data.IWidget
    {
        [DataMember]
        public String ID { get; set; }
        [DataMember]
        public virtual ICollection<IWidgetPiece> Pieces { get; set; }
    }

    [DataContract(IsReference = true)]
    public partial class WidgetPiece : QA.Data.IWidgetPiece
    {
        [DataMember]
        public string ID { get; set; }
    }

}


namespace QA.Repository
{
    public class WidgetRepository
    {
        public List<Widget> GetWidgetbyID(String sId)
        {
            WidgetEntities context = new WidgetEntities();
            List<IWidget> objs = context.Widgets.Where(b => b.ID == "78").ToList();

            List<Widget> widgetList = new List<Widget>();
            foreach (var iwidget in widgetList)
                widgetList((Widget)iwidget);

            return widgetList;
        }
    }
}

【问题讨论】:

    标签: wcf entity-framework domain-driven-design


    【解决方案1】:

    您真的想要/需要两个独立的模型,即您的数据访问层模型 (edmx) 和您的“真实”域模型吗?像 EF 这样的 ORM 框架的全部意义在于,您可以使用物理(数据库)概念模型之间的映射将域模型映射到数据库表。

    从 EF4.1 开始,您可以构建域模型,然后在数据访问层中使用流式 API 直接将其映射到您的数据库。如果您想快速启动运行,您还可以选择从数据库中对 POCO 域模型进行逆向工程。

    创建整个 EF 类模型似乎有点不必要的复杂性,然后必须再次将其映射到另一个类模型(很可能与 EF 生成的模型相当接近)。

    【讨论】:

    • 此设计将成为面向服务平台的基础,因此其想法是分离类/域模型和 EF 之间的任何依赖关系。数据存储和域类必须能够相互独立地更改。我的训练是 DATA 层不应该引用 DOMAIN 层。正如您所建议的,将域对象映射到底层 EF 类模型需要从 DATA 层/项目直接引用到 DOMAIN 层/项目。这使我无法从 DOMAIN 项目中引用 DATA 项目(循环引用异常)。
    • 是的,这一切都很好。务实一点-您是否真的打算将您的域模型呈现给多个客户等等-如果是这样,那就去做吧。否则,请认真考虑将您的映射放在 ORM 中。您始终可以为自己创建一个简单的 EF 模型,然后再构建一个“公共”API。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-07-08
    • 2017-07-04
    • 2013-04-08
    • 1970-01-01
    相关资源
    最近更新 更多