0

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

我正在使用 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();
        }
    }
}
4

3 回答 3

0

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

经过多次搜索后,除了将 EF 类映射到与 EF 类完全相同的等效 DTO 类之外,我找不到任何解决方案,除了 Navigation 属性和构造函数(即我已经剥离了所有虚拟属性(如 ICollection 的)和 ctor来自 EF 类,并从中创建了一个与我的 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>();
于 2013-04-30T12:28:48.413 回答
0

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

于 2013-04-30T16:47:40.817 回答
0

您需要使用 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,而实体框架可以使用实体。

于 2013-04-18T08:24:06.840 回答