2015-02-23 15 views
1

我有一個POCO類BankAccount這是public和所有的成員都public properties和導航屬性設置爲virtual這是什麼EF6行爲查找原因()不返回一個代理,但單()不會返回代理

實體框架6.1.2使用Find()方法從數據庫正確加載它作爲POCO。但是,據我所知,它應該返回一個Proxy類實例而不是POCO實例!實際上,當我使用Single()SingleOrDefault(),First()FirstOrDefault()代理類實例正確返回。

這是怎麼回事,這是預期的行爲,如果不是什麼會導致這種情況發生?

下面是POCO類:

using System; 
using System.Collections.Generic; 
using System.ComponentModel.DataAnnotations; 
using System.ComponentModel.DataAnnotations.Schema; 
using System.Linq; 
using System.Runtime.Serialization; 

namespace AbcBankModels 
{ 
    //[DataContract] 
    [Table("BankAccount")] 
    public class BankAccount 
    { 
     [Key] 
     [Column(Order = 1)] 
     //[DataMember] 
     //[Range(0, 9999999)] 
     //[StringLength(7, MinimumLength = 7)] 
     //[Display(Name = "Account Number")] 
     public virtual string BankAccountId { get; set; } 

     [Key] 
     [Column(Order = 2)] 
     //[DataMember] 
     //[Range(0, 999999)] 
     //[StringLength(6, MinimumLength = 6)] 
     //[Display(Name = "Sort Code")] 
     public virtual string BankBranchId { get; set; } 

     //[DataMember] 
     public virtual BankBranch BankBranch { get; set; } 

     //[DataMember] 
     //[ForeignKey("ApplicationUser")] 
     public virtual string ApplicationUserId { get; set; } 

     //[DataMember] 
     public virtual User ApplicationUser { get; set; } 

     //[DataMember] 
     public virtual ICollection<BankCard> BankCardList { get; set; } 

     //[DataMember] 
     public virtual ICollection<BankTransaction> BankTransactionList { get; set; } 

     //[DataMember] 
     //[Display(Name = "Account Status")] 
     //[EnumDataType(typeof(EnumAccountStatus))] 
     public virtual EnumAccountStatus AccountStatus { get; set; } 

     //[DataMember] 
     //[Display(Name = "Account Type")] 
     //[EnumDataType(typeof(EnumBankAccountType))] 
     public virtual EnumBankAccountType AccountType { get; set; } 

     //[DataMember] 
     //[DataType(DataType.DateTime)] 
     //[Display(Name = "Date Account Opened")] 
     public virtual DateTime? AccountCreationDateTime { get; set; } 

     //[DataMember] 
     //[DataType(DataType.DateTime)] 
     //[Display(Name = "Date Account Closed")] 
     public virtual DateTime? AccountClosureDateTime { get; set; } 

     //[DataMember] 
     //[DataType(DataType.Currency)] 
     //[Display(Name = "Account Overdraft Limit")] 
     public virtual decimal AccountOverdraft { get; set; } 

     //[DataMember] 
     //[Display(Name = "Account Overdraft Interest Rate")] 
     public virtual decimal AccountOverdraftInterestRate { get; set; } 

     //[DataMember] 
     //[Display(Name = "Account Overdraft Usage Monthly Fee")] 
     public virtual decimal AccountOverdraftFacilityMonthlyCost { get; set; } 

     //[DataMember] 
     //[Display(Name = "Account Monthly Fee")] 
     public virtual decimal AccountMonthlyCost { get; set; } 

     //[DataMember] 
     //[Display(Name = "Account Interest Rate")] 
     public virtual decimal AccountInterestRate { get; set; } 

    } 
} 

這裏是一個不會返回代理的方法:

public static BankAccount FindBankAccount(ApplicationDbContext applicationDbContext, string bankAccountId, string bankBranchId, string userId) 
    { 
     if (String.IsNullOrWhiteSpace(bankAccountId) || String.IsNullOrWhiteSpace(bankBranchId)) return null; 

     var bankAccount = applicationDbContext.BankAccountList.SingleOrDefault(a => a.BankAccountId == bankAccountId && a.BankBranchId == bankBranchId); 

     if (bankAccount == null) return null; 

     if (string.IsNullOrWhiteSpace(userId)) return bankAccount; 

     if (bankAccount.ApplicationUserId != userId) return null; 

     return bankAccount; 
    } 

這裏是一個不返回代理的方法:

public static BankAccount FindBankAccount(ApplicationDbContext applicationDbContext, string bankAccountId, 
     string bankBranchId, string userId) 
    { 
     if (String.IsNullOrWhiteSpace(bankAccountId) || String.IsNullOrWhiteSpace(bankBranchId)) return null; 

     var bankAccount = applicationDbContext.BankAccountList.Find(bankAccountId, bankBranchId); 

     if (bankAccount == null) return null; 

     if (string.IsNullOrWhiteSpace(userId)) return bankAccount; 

     if (bankAccount.ApplicationUserId != userId) return null; 

     return bankAccount; 
    } 

回答

1

如果您的上下文在您查詢的那一刻已經使用該密鑰跟蹤了非代理BankAccount,則可能會發生這種情況它。

奇怪的是,儘管First和Single總是查詢數據庫,但它們應該返回與Find相同的實體。

例如,如果您有運行該代碼單元測試:

 Foo nonProxy = new Foo { Id = 4, Name = "Foo 4" }; // values correspond to an existing entity in db 
     ApplicationDbContext ctx = new ApplicationDbContext();   
     ctx.Foos.Attach(nonProxy); 
     Assert.AreSame(nonProxy, ctx.Foos.Find(nonProxy.Id)); 
     Assert.AreSame(nonProxy, ctx.Foos.First(c => c.Name == "Foo 4")); 
     Assert.AreSame(nonProxy, ctx.Foos.FirstOrDefault(c => c.Name == "Foo 4")); 
     Assert.AreSame(nonProxy, ctx.Foos.Single(c => c.Name == "Foo 4")); 
     Assert.AreSame(nonProxy, ctx.Foos.SingleOrDefault(c => c.Name == "Foo 4")); 

     ctx = new ApplicationDbContext(); 
     Foo proxy = ctx.Foos.Find(nonProxy.Id); 
     Assert.AreSame(proxy, ctx.Foos.Find(nonProxy.Id)); 
     Assert.AreSame(proxy, ctx.Foos.First(c => c.Name == "Foo 4")); 
     Assert.AreSame(proxy, ctx.Foos.FirstOrDefault(c => c.Name == "Foo 4")); 
     Assert.AreSame(proxy, ctx.Foos.Single(c => c.Name == "Foo 4")); 
     Assert.AreSame(proxy, ctx.Foos.SingleOrDefault(c => c.Name == "Foo 4")); 

,那麼它應該沒有錯誤運行。在上下文跟蹤具有相同鍵的實體之後,它們都返回對同一對象的引用。

參考Querying/Finding Entities

// Query for the Blog named ADO.NET Blog 
var blog = context.Blogs.Where(b => b.Name == "ADO.NET Blog").FirstOrDefault(); 

當結果被從數據庫返回的,不存在的背景下, 對象附加到上下文。如果對象已經在 上下文中,則返回現有對象(該條目中對象屬性的當前和原始值 不會被數據庫值覆蓋 )。

所以,你可能正在使用中的情況下已經有一個非代理實體與關鍵上下文跟蹤查找,或者你在代碼中的某個地方使用它之前禁用Configuration.ProxyCreationEnabled。可能還有用:DbSet.Find Method

相關問題