WCF服务消耗EF-Agnostic设计的问题。

时间:2012-10-03 20:59:02

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

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

代码分为3个项目。 (我正在尝试DDD - 我很陌生,但我很期待学习更多)

    Project: QA - Domain Layer. Contains the DataContract models/entities.
        References 
            QA.Data

    Project: QA.Data - Data Layer. Contains the context and EDMX (code generation stragtegy = "none")
        References
            Entity Framework/System.Data.Entity

    Project: QA.Repository - Data Access/Repository. Contains the repository classes
        References
            QA [Domain Layer]
            QA.Data [Data Layer]
            Entity Frame/System.DataEntity

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

我的(失败的)解决方案:我的解决方案是为每个域模型创建接口并将它们放在数据层中。上下文将返回... 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'已经存在。如果   有不同的特定类型的集合 - 例如,   列表和测试[],它们不能同时作为已知类型添加。   请考虑仅指定其中一种类型以添加​​到已知类型   类型列表。

我可以将这些更改为具体实现... [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;
        }
    }
}

1 个答案:

答案 0 :(得分:0)

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

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

创建一个完整的EF类模型似乎有点不必要的复杂性,然后只需要将它再次映射到另一个类模型(很可能非常接近EF生成的模型)。