Vs2012 + WCF上的ADO.NET实体框架=错误

时间:2013-04-18 08:00:17

标签: wcf entity-framework-5

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

我正在使用VSO使用ADO.NET实体框架开发一个解决方案(5我认为,最新版本)。一切正常,直到我将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();
        }
    }
}

3 个答案:

答案 0 :(得分: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,实体框架可以使用该实体。

答案 1 :(得分:0)

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

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

我使用 AutoMapper 自动将EF对象映射到Dto等效对象。 E.g:

   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>();

答案 2 :(得分:0)

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

相关问题