C# WCF和EF中的System.InvalidOperationException

C# WCF和EF中的System.InvalidOperationException,c#,entity-framework,wcf,C#,Entity Framework,Wcf,我有一个包含4个项目(XYZ.Domain、XYZ.Data、XYZ.Service和XYZ.Client)的解决方案(XYZ)。我需要运行WCF web服务。这是我的代码: namespace XYZ.Domain { using System; using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using System.Linq; using S

我有一个包含4个项目(XYZ.Domain、XYZ.Data、XYZ.Service和XYZ.Client)的解决方案(XYZ)。我需要运行WCF web服务。这是我的代码:

namespace XYZ.Domain
{
    using System;
    using System.Collections.Generic;
    using System.ComponentModel.DataAnnotations;
    using System.Linq;
    using System.Runtime.Serialization;
    using System.Text;
    using System.Threading.Tasks;

    // Updated properties
    [DataContract]
    public class X : BaseClass
    {
        [DataMember]
        [Key]
        public int Xx { get; set; }

        [DataMember]
        [Required]
        [StringLength(15)]
        public string Xy { get; set; }

        [DataMember]
        public bool Xz { get; set; }

        // Relationship with Y 1:1
        [DataMember]
        public virtual Y y { get; set; }
    }

    // Updated properties
    [DataContract]
    public class Y : BaseClass
    {
        [DataMember]
        [Key]
        [DatabaseGenerated(DatabaseGeneratedOption.None)]
        public int Yx {get; set;}

        [DataMember]
        [Required]
        [StringLength(15)]
        public string Yy {get; set;}

        [DataMember]
        public DateTime Yz {get; set;}

        // foreign key from Z
        [DataMember]
        public int Zx {get; set;}

        // Relationship with X 1:1
        [DataMember]
        public virtual X x {get; set;}

        // Relationship with Z *:1
        [DataMember]
        public virtual Z z { get; set; }
    }

    // Updated properties
    [DataContract]
    public class Z : BaseClass
    {
        public Z()
        {
            this.y = new HashSet<Y>();
        }

        [DataMember]
        [Key]
        public int Zx {get; set;}

        [DataMember]
        public DateTime Zy {get; set;}

        [DataMember]
        [Required]
        public float Zz {get; set;}

        // Relationship with Y 1:*
        [DataMember]
        public virtual ICollection<Y> y { get; set; }
    }

    // Added as a base class for my IServiceXYZ 
    [KnownType(typeof(X))]
    [KnownType(typeof(Y))]
    [KnownType(typeof(Z))]
    [DataContract]
    public class BaseClass
    {
        // empty
    }
}
但这是一个错误:

XYZ.Data.dll中发生“System.InvalidOperationException”类型的异常,但未在用户代码中处理


附加信息:实体类型基类不是当前上下文模型的一部分。

使用基于泛型的服务契约不是一个好主意,您必须使用服务契约的所有可能数据类型更新web.config

如果坚持这种类型的配置,则需要让WCF服务使用序列化程序,该序列化程序将在有效负载中嵌入CLR数据类型信息。NetdataContractSerializer可以做到这一点,您还应该拥有客户端和服务器共享的公共程序集来保存这些数据类型

如果你想做“纯”的WCF,那么你所做的并不是要与你必须面对的所有的“gotcha”做斗争

您可以创建一个服务来发送属于某个基类的子类的任何对象,例如,如果您的类X、Y和Z都扩展了一个基类(我们称之为
BaseClass
),那么您的服务契约就可以基于此

所以你最终会得到这样的服务:

public class ServiceXYZ : IServiceXYZ
{
    // XYZ.Data persistence object



    public void Insert(BaseClass entity)
    {
        //get EF Context 
        var Context = new Entities();  // <-- some method to get your EF context
        Context.Entry(entity).State = Added;  //<- this will attach and add         
    }
您需要更改数据契约以扩展
基类

[KnownType(typeof(X)]
[KnownType(typeof(Y)]
[KnownType(typeof(Z)]
[DataContract]
public class BaseClass
{
    ...
}
[DataContract]   
public class X : BaseClass  { ...}

[DataContract]   
public class Y : BaseClass  { ...}

[DataContract]   
public class Z : BaseClass  { ...}
更新

[ServiceContract]
public interface IServiceXYZ   // NO GENERICS!! YOU BASE CLASS
{
    [OperationContract]
    void Insert(BaseClass entity);

    [OperationContract]
    void Update(BaseClass entity);

    [OperationContract]
    void Delete(BaseClass entity);
}

正如我在上面已经解释过的,您可以通过使用上下文和设置实体状态来简单地附加实体。看看我所做的服务类的实现…

我已经做了我们正在尝试的,相信我,按照我下面建议的方式来实现它。泛型对于WCF Soap服务来说不是一个可行的选项。最佳实践是不要一路共享实体,而只在数据层保留它们,而是创建它们的POCO表示,并传递POCO的信息。从您正在进行的紧耦合中抽象出来。它会帮你省去很多麻烦和问题。它们应该包含它们的所有属性。不,我认为你不了解它是如何工作的。你是先做DB的代码第一吗?我已经实现了这一点,它工作得非常好。您的方法可以接受
基类
类型的参数,但是是X、Y或Z的实例。。。。试试看。。。通过网络传递一个X的实例,然后在服务器上将其状态设置为added,但仍然是错误的,WCF接口和实现不能有泛型,去掉它们!!!我很抱歉@T McKeown,你说得对。我更改了这一行:_context.Set().Add(entity);对于另一个:_context.Entry(entity.State=EntityState.Added;而且它是有效的!。。。我唯一的问题是当我试图从一个特定的表中获取所有信息时。不过没关系,谢谢你们这么多人!。
[KnownType(typeof(X)]
[KnownType(typeof(Y)]
[KnownType(typeof(Z)]
[DataContract]
public class BaseClass
{
    ...
}
[DataContract]   
public class X : BaseClass  { ...}

[DataContract]   
public class Y : BaseClass  { ...}

[DataContract]   
public class Z : BaseClass  { ...}
[ServiceContract]
public interface IServiceXYZ   // NO GENERICS!! YOU BASE CLASS
{
    [OperationContract]
    void Insert(BaseClass entity);

    [OperationContract]
    void Update(BaseClass entity);

    [OperationContract]
    void Delete(BaseClass entity);
}