【问题标题】:ADO.NET Entity Framework on Vs2012 + WCF = ErrorVs2012 上的 ADO.NET 实体框架 + WCF = 错误
【发布时间】:2013-04-18 08:00:16
【问题描述】:

首先,感谢您阅读我的问题。

我正在使用 VS 2012 使用 ADO.NET Entity Framework(我认为是最新版本)开发一个解决方案。一切正常,直到我将 WCF 服务作为业务层引入(这是学校的作业,我不能从业务层废弃 WCF)。

问题是当我从数据库请求数据时。当我有一个从数据库返回字符串的方法时,它工作得很好(因为它是一个原语)。但是当它返回一个 Entity 对象(例如 Account)时,一切都变了。

例外:(是的,它非常模糊)。

An error occurred while receiving the HTTP response to http://localhost:8733/Services/AccountsManager. This could be due to the service endpoint binding not using the HTTP protocol. This could also be due to an HTTP request context being aborted by the server (possibly due to the service shutting down). See server logs for more details.

我尝试了什么:我尝试修改 Entites.tt 文件以添加 [DataContract] [DataMember] 属性。这是因为在旧版本的 EF 中,它似乎是自己做的。但我不知道这是否有必要,因为它允许我编译并且不会抱怨它不可序列化。

这是它最初的样子:

namespace CommonLayer
{
using System;
using System.Collections.Generic;

 public partial class Account
{
    public Account()
    {
        this.Transactions = new HashSet<Transaction>();
        this.Transactions1 = new HashSet<Transaction>();
    }

    public System.Guid ID { get; set; }
    public int Type { get; set; }
    public string Name { get; set; }
    public int Currency { get; set; }
    public decimal Balance { get; set; }
    public System.DateTime DateOpened { get; set; }
    public Nullable<int> Duration { get; set; }
    public string UserName { get; set; }

    public virtual AccountType AccountType { get; set; }
    public virtual Currency Currency1 { get; set; }
    public virtual User User { get; set; }
    public virtual ICollection<Transaction> Transactions { get; set; }
    public virtual ICollection<Transaction> Transactions1 { get; set; }
}
}

修改后的样子:

namespace CommonLayer
{
using System;
using System.Collections.Generic;
using System.Runtime.Serialization;
[DataContract] public partial class Account
{
    public Account()
    {
        this.Transactions = new HashSet<Transaction>();
        this.Transactions1 = new HashSet<Transaction>();
    }

    [DataMember] public System.Guid ID { get; set; }
    [DataMember] public int Type { get; set; }
    [DataMember] public string Name { get; set; }
    [DataMember] public int Currency { get; set; }
    [DataMember] public decimal Balance { get; set; }
    [DataMember] public System.DateTime DateOpened { get; set; }
    [DataMember] public Nullable<int> Duration { get; set; }
    [DataMember] public string UserName { get; set; }

    public virtual AccountType AccountType { get; set; }
    public virtual Currency Currency1 { get; set; }
    public virtual User User { get; set; }
    public virtual ICollection<Transaction> Transactions { get; set; }
    public virtual ICollection<Transaction> Transactions1 { get; set; }
}
}

非常感谢任何指针。

我的 WCF 课程

using System;
using System.Collections.Generic;
using System.Linq;
using System.ServiceModel;
using System.Text;
using System.Threading.Tasks;

namespace BusinessLayer
{

    [ServiceContract]
    interface IAccountsManager
    {
        [OperationContract]
        List<CommonLayer.Account> GetAccounts(String UserName);

        [OperationContract]
        String GetData();

        [OperationContract]
        CommonLayer.Account GetAccount(String UserName);
    }

    class AccountsManager: IAccountsManager, IDisposable
    {
        public List<CommonLayer.Account> GetAccounts(String UserName)
        {
            return DataLayer.AccountsRepository.Instance.GetAccountList(UserName).ToList();
        }

        public String GetData()
        {
            CommonLayer.Account acc  = this.GetAccounts("test").FirstOrDefault();
            return acc.DateOpened.ToString();
        }

        public CommonLayer.Account GetAccount(String UserName)
        {
            return this.GetAccounts(UserName).FirstOrDefault();
        }

        public void Dispose()
        {
            DataLayer.AccountsRepository.Reset();
        }
    }
}

【问题讨论】:

  • 您可以编辑您的问题并添加您的 WCF 服务方法吗?
  • 按要求编辑。从这些方法中,“GetData 方法有效”。其他方法没有。

标签: wcf entity-framework-5


【解决方案1】:

您需要使用 DTO(数据传输对象)并将 EF 对象映射到您的 DTO。

所以服务可能会接受一个名为 MyDto 的对象,看起来像:

[DataContract]
public class MyDto {
    [DataMember]
    public int Id {get;set;}
}

和一个带有方法的静态映射类

public static MyEntity Map(MyDto dto) {
    return new MyEntity { Id = dto.Id };
}

public static MyDto Map(MyEntity entity) {
    return new MyDto { Id = entity.Id };
}

然后您可以根据需要进行映射,以便服务可以使用 DTO,而实体框架可以使用实体。

【讨论】:

    【解决方案2】:

    似乎当 EF 类具有导航属性(如您的类中的 ICollection&lt;Transaction&gt; Transactions)时,它在通过 WCF 传输时会失败。

    经过多次搜索,除了将 EF 类映射到与 EF 类完全相同的等效 DTO 类之外,我找不到任何解决方案,除了 Navigation 属性和构造函数(即,我已经剥离了所有虚拟属性(如 ICollection 的)以及来自 EF 类的 ctor,并从中创建了一个与我的 EF 类相同的新类以及 Dto 后缀(例如 CustomerDto)。

    我使用 AutoMapper 自动将 EF 对象映射到 Dto 等效对象。例如:

       var customer = getCustomer(cid);
    
       var customerDto = Mapper.Map<CustomerDto>(customer);
    
       return customerDto;
    

    我的 WCF 合同包括

    [OperationContract]
    CustomerDto getCustomerData(int cid);
    

    此外,我还需要对 Mapper 进行一次初始化。我在 Global.asax 中完成了如下操作:

    Mapper.CreateMap<Customer, CustomerDto>();
    

    【讨论】:

      【解决方案3】:

      我所做的是更改了我的 Entities.Edmx 文件。首先,我删除了所有 (2) 个“.tt”文件。然后我将代码生成策略从无更改为默认。这似乎解决了我所有的问题。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-12-26
        • 1970-01-01
        • 2016-06-29
        相关资源
        最近更新 更多