【问题标题】:WCF with Entity Framework Code First relationshipWCF 与实体框架代码优先关系
【发布时间】:2011-10-25 21:13:49
【问题描述】:

我正在学习 WCF,并尝试制作一个小服务来公开项目及其任务(标准实体框架 hello world)。

类结构如下:

public class Project
{
    public int ProjectId { get; set; }
    public string Name { get; set; }
    public string Description { get; set; }
    public DateTime CreationDate { get; set; }
    public virtual ICollection<Task> Tasks { get; set; }
}

public class Task
{
    public int TaskId { get; set; }
    public string Title { get; set; }
    public virtual Project RelatedProject { get; set; }
}

数据库上下文出现在:

public class ProjectContext : DbContext
{
    public DbSet<Project> Projects { get; set; }
    public DbSet<Task> Tasks { get; set; }
}

最后是服务端点:

    public IEnumerable<Project> getProjects()
    {
        ProjectContext p = new ProjectContext();
        return p.Projects.AsEnumerable();
    }

问题是这个模型会抛出 System.ServiceModel.CommunicationException,但是,如果我从模型中删除虚拟属性,它会起作用,但我会失去 Project 和 Task 之间的实体框架链接。

有类似设置的人吗?

【问题讨论】:

  • 如果包含Tasks 是否有效? return p.Projects.Include(p =&gt; p.Tasks).AsEnumerable();
  • 这甚至不会编译,但我明白了这个想法,我会遵循这个选项;)
  • 嗯,没试过(显然),但在ADO.NET Team Blog 上找到了:\

标签: wcf entity-framework


【解决方案1】:

我用这个把头撞在墙上几个小时。经过大量调试,谷歌给出了答案,我觉得在这里发布它是正确的,因为这是我在谷歌得到的第一个结果。

在你的[ServiceContract]接口声明之上添加这个类(通常是IProjectService.cs

public class ApplyDataContractResolverAttribute : Attribute, IOperationBehavior
{
    public void AddBindingParameters(OperationDescription description, BindingParameterCollection parameters)
    {

    }

    public void ApplyClientBehavior(OperationDescription description, System.ServiceModel.Dispatcher.ClientOperation proxy)
    {
        var dataContractSerializerOperationBehavior =
            description.Behaviors.Find<DataContractSerializerOperationBehavior>();
        dataContractSerializerOperationBehavior.DataContractResolver =
            new ProxyDataContractResolver();
    }

    public void ApplyDispatchBehavior(OperationDescription description, System.ServiceModel.Dispatcher.DispatchOperation dispatch)
    {
        var dataContractSerializerOperationBehavior =
            description.Behaviors.Find<DataContractSerializerOperationBehavior>();
        dataContractSerializerOperationBehavior.DataContractResolver =
            new ProxyDataContractResolver();
    }

    public void Validate(OperationDescription description)
    {
        // Do validation.
    }
}

要求是

using System.ServiceModel.Description;
using System.Data.Objects;
using System.ServiceModel.Channels;

然后在[OperationContract] 关键字下添加[ApplyDataContractResolver] 关键字即可!

非常感谢http://blog.rsuter.com/?p=286

【讨论】:

    【解决方案2】:

    要通过 WCF 发送数据,您应该禁用延迟加载 (dataContext.ContextOptions.LazyLoadingEnabled = false;)。

    要确保加载所需的数据,您需要使用预先加载(通过 Include 方法)。

    您需要将您的功能更改为:

     public IEnumerable<Project> getProjects()
        {
            ProjectContext p = new ProjectContext();
            p.ContextOptions.LazyLoadingEnabled = false;
    
            return p.Projects.Include("Tasks").AsEnumerable();
        }
    

    【讨论】:

    • 不走运,仍然出现这个错误:服务器没有提供有意义的回复;这可能是由于合同不匹配、会话过早关闭或内部服务器错误造成的。
    猜你喜欢
    • 1970-01-01
    • 2012-10-11
    • 2017-07-05
    • 1970-01-01
    • 1970-01-01
    • 2012-03-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多