2013-04-18 38 views
0

首先,感謝您閱讀我的問題。Vs2012上的ADO.NET實體框架+ WCF =錯誤

我正在開發一個使用VS 2012使用ADO.NET實體框架(5我認爲,最新版本)的解決方案。所有工作都很好,直到我將WCF服務作爲業務層引入(這是學校的一項任務,我無法從業務層中取消WCF)。

問題是,當我從數據庫請求數據。當我有一個從數據庫返回字符串的方法時,它工作得很好(因爲它是一個原語)。但是,當它返回一個實體對象(如帳戶)時,一切都會到了地獄。

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

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] [數據成員]屬性。這是因爲在較早版本的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(); 
     } 
    } 
} 
+0

你能編輯你的問題並添加你的WCF服務方法嗎? –

+0

按要求編輯。從這些方法,在「GetData方法工作」。其他方法不。 –

回答

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和實體框架可以使用實體。

0

看來,當EF類具有導航屬性(例如類中的ICollection<Transaction> Transactions)時,它將在通過WCF傳輸時失敗。

經過許多搜索後,我找不到任何解決方案,除了將EF類映射到與EF類完全相同的DTO類中,除了導航屬性和構造函數外(即,我已將所有虛擬屬性(如ICollection類),並從EF類構造函數,並從一個新的類名爲同我的EF類加後綴的DTO(如CustomerDto)創建的。

我用AutoMapper自動映射的EF對象爲DTO - 等價的一個。G:

var customer = getCustomer(cid); 

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

    return customerDto; 

我的WCF合同包括

[OperationContract] 
CustomerDto getCustomerData(int cid); 

除了我需要做的映射的一次初始化。我已經在Global.asax中完成了如下操作:

Mapper.CreateMap<Customer, CustomerDto>(); 
0

我所做的是改變了我的Entities.Edmx文件。首先,我刪除了所有(2)「.tt」文件。然後我將代碼生成策略從None更改爲Default。這似乎解決了我所有的問題。