WCF服务使用的EF不可知设计问题。

WCF服务使用的EF不可知设计问题。,wcf,entity-framework,domain-driven-design,Wcf,Entity Framework,Domain Driven Design,我正在尝试设置EF来处理WCF,并保持域类模型EF不可知 代码分为3个项目。(我正在尝试DDD——我对它很陌生,但我期待了解更多) 项目:QA-域层。包含DataContract模型/实体。 工具书类 质量保证数据 项目:QA.Data-数据层。包含上下文和EDMX(代码生成stragtegy=“无”) 工具书类 实体框架/System.Data.Entity 项目:QA.Repository-数据访问/存储库。包含存储库类 工具书类 QA[域层] QA.Data[数据层] 实体框架/Syste

我正在尝试设置EF来处理WCF,并保持域类模型EF不可知

代码分为3个项目。(我正在尝试DDD——我对它很陌生,但我期待了解更多)

项目:QA-域层。包含DataContract模型/实体。 工具书类 质量保证数据 项目:QA.Data-数据层。包含上下文和EDMX(代码生成stragtegy=“无”) 工具书类 实体框架/System.Data.Entity 项目:QA.Repository-数据访问/存储库。包含存储库类 工具书类 QA[域层] QA.Data[数据层] 实体框架/System.DataEntity 我的理解是,域层可以引用数据层,但数据层不应该引用域。这带来的问题是,我的域模型/类在域层中定义,但创建和返回它们的上下文在数据层中。为了让我的上下文知道返回一个“Widget”对象,它需要一个对定义“Widget”的域层的引用

我的(失败的)解决方案:我的解决方案是为每个域模型创建接口,并将它们放在数据层中。上下文将返回。。。IdbSet。。。反过来,这些接口将由域模型实现,因此我的数据层不需要直接引用我的域(这会导致非法的循环引用)。域模型最初是使用“ADO.NET DbContext Generator w/WCF Support”T4模板构建的。这个过程导致在小部件类定义的开头包含[KnownType(typeof(IWidgetPiece))]。(小部件具有导航属性…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;
        }
    }
}
名称空间QA.Data
{
公共接口IWidgetPiece
{
字符串ID{get;set;}
}
公共接口IWidget
{
字符串ID{get;set;}
i收集碎片;
}
公共部分类WidgetEntities:DbContext
{
IDbSet小部件{get;set;}
IDbSet WidgetPieces{get;set;}
}
}
名称空间QA
{
[KnownType(typeof(IWidgetPiece))]
//[KnownType(typeof(WidgetPiece))]
[DataContract(IsReference=true)]
公共部分类小部件:QA.Data.IWidget
{
[数据成员]
公共字符串ID{get;set;}
[数据成员]
公共虚拟ICollection片段{get;set;}
}
[DataContract(IsReference=true)]
公共部分类WidgetPiece:QA.Data.IWidgetPiece
{
[数据成员]
公共字符串ID{get;set;}
}
}
名称空间QA.Repository
{
公共类WidgetRepository
{
公共列表GetWidgetbyID(字符串sId)
{
WidgetEntities上下文=新的WidgetEntities();
列出objs=context.Widgets.Where(b=>b.ID==“78”).ToList();
List widgetList=新列表();
foreach(widgetList中的变量iwidget)
widgetList((小部件)iwidget);
返回widgetList;
}
}
}

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

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


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

此设计将是面向服务的平台的基础,其思想是分离类/域模型和EF之间的任何依赖关系。数据存储和域类必须能够相互独立地更改。我的培训是数据层不应该引用域层。正如您所建议的,将域对象映射到底层EF类模型将需要从数据层/项目直接引用到域层/项目。这使我无法从域项目引用数据项目(循环引用异常)。是的,这很好。只要务实一点——你真的打算向多个客户展示你的领域模型吗?等等——如果是的话,那就去做吧。否则,认真考虑把你的映射放在ORM中。你总是可以做些什么
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;
        }
    }
}