2014-09-28 12 views
4

時爲空我有一個Account類持有Payments一個列表,其中包含的ProductsPendingSoldRefunded列表。MVC5 EF實體明顯節省,但檢索

當選擇Products來支付時,我可以將它們添加到一個Payment對象中,然後將整個對象保存到Account

但是,當我檢索Pay操作中的帳戶時,Account.Payments爲空。

這裏是AddProduct行動:

public ActionResult AddProduct(List<Product> products) 
{ 
    //var acc = Account.FetchAccountFromIdentity(User.Identity.GetUserName()); 
    var username = User.Identity.GetUserName(); 
    var acc = db.Accounts.First(u => u.EmailAddress == username); 
    var payment = new Payment(); 

    foreach (var product in products) 
    { 
     if (product.IsSelected) 
     { 
      var tempProduct = db.Products.Find(product.ProductID); 
      payment.Products.Add(tempProduct); 
      payment.PaymentStatus = enPaymentStatus.Pending; 
      payment.Gross += tempProduct.Price; 
      payment.Vat += tempProduct.Price * 0.2; 
      payment.Net += payment.Gross - payment.Vat; 
     } 
    } 
    payment.AccountID = acc; 
    if (acc.Payments == null) acc.Payments = new List<Payment>(); 
    acc.Payments.Add(payment); 
    db.SaveChanges(); 

    return RedirectToAction("Pay", "Products", new {id = acc.AccountID}); 
} 

acc.Payments正確填入在這一點上任何相關款項。

然後是Pay行動:

public ActionResult Pay(int? id) 
    { 
     var acc = db.Accounts.Find(id); 
     var data = new AccountPaymentView 
     { 
      Account = acc, 
      Payment = acc.Payments.First(p => p.PaymentStatus == enPaymentStatus.Pending) 
     }; 

     return View(data); 
    } 

acc.Payments現在是空!?

任何想法,我必須做錯什麼?

與帳戶類編緝 目前:

public class Account 
    { 
     [Key] 
     [DatabaseGenerated(DatabaseGeneratedOption.Identity)] 
     public int AccountID { get; set; } 
     [Display(Name = "Title")] 
     public string Salutation { get; set; } 
     [Required] 
     [Display(Name = "First Name")] 
     public string FirstName { get; set; } 
     [Required] 
     [Display(Name = "Last Name")] 
     public string LastName { get; set; } 
     [Required] 
     [DataType(DataType.Password)] 
     [Display(Name = "Password")] 
     public string Password { get; set; } 
     [Required] 
     [DataType(DataType.Password)] 
     [Compare("Password", ErrorMessage = "Passwords do not match. Please try again.")] 
     [Display(Name = "Confirm Password")] 
     public string ConfirmPass { get; set; } 
     [Required] 
     [DataType(DataType.EmailAddress)] 
     [Display(Name = "Email Address")] 
     public string EmailAddress { get; set; } 
     public virtual ICollection<Address> Addresses { get; set; } 
     public virtual ICollection<Payment> Payments { get; set; } 
     public DateTime CreatedOn { get; set; } 
     public virtual ICollection<DateTime> VistsList { get; set; } 
     public bool IsDeleted { get; set; } 
     public enAccountType AccountType { get; set; } 
} 

編輯2 這裏是關於的DbContext(刪除不相關的部分)的方法OnModelCreating。我想知道一些顯而易見的事情嗎?

protected override void OnModelCreating(DbModelBuilder modelBuilder) 
{ 
    base.OnModelCreating(modelBuilder); 

    modelBuilder.Properties<DateTime>() 
     .Configure(c => c.HasColumnType("datetime2")); 

    modelBuilder.Entity<Account>().HasOptional(x => x.Addresses).WithMany(); 
    modelBuilder.Entity<Account>().HasOptional(x => x.Payments).WithMany(); 
    modelBuilder.Entity<Payment>().HasOptional(x => x.Products).WithMany(); 
    modelBuilder.Entity<Payment>().HasOptional(x => x.AccountID); 
    modelBuilder.Entity<Payment>().HasKey(x => x.PaymentID); 

} 

編輯3 簽出Account.FetchAccountFromIdentity()和它打開一個新的上下文。所以現在已經被刪除了,現在我在AddProduct方法中使用一個上下文(上面更新的代碼)。

現在我在保存時出現以下錯誤!

An object of type 'System.Collections.Generic.List`1[[PPPv2.Models.Payment, PPPv2, 
Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]]' 
cannot be set or removed from the Value property of an EntityReference of type 'PPPv2.Models.Payment'. 

我試過在OnModelCreating方法中強制PK關係,但它似乎沒有幫助。

爲了清楚起見,這裏是支付類:

public class Payment 
{ 
    [Key] 
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)] 
    public int PaymentID { get; set; } 
    public virtual Account AccountID { get; set; } 
    public virtual ICollection<Product> Products { get; set; } 
    public double Gross { get; set; } 
    public double Net { get; set; } 
    public double Vat { get; set; } 
    public string TransactionCode { get; set; } 
    public enPaymentStatus PaymentStatus { get; set; } 
    public bool IsDeleted { get; set; } 
    public DateTime PaidOn { get; set; } 

    public Payment() 
    { 
     Products = new List<Product>(); 
     Gross = 0.0; 
     Net = 0.0; 
     Vat = 0.0; 
     IsDeleted = false; 
     PaidOn = new DateTime(2000, 1, 1, 0, 0,0); 
    } 

} 

編輯4 按照要求,這裏是產品型號:

public class Product 
{ 
    [Key] 
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)] 
    public int ProductID { get; set; } 
    public string Name { get; set; } 
    public string Description { get; set; } 
    [DataType(DataType.Currency)] 
    [DisplayFormat(DataFormatString = "£{0:#,###0.00}")] 
    public double Price { get; set; } 
    [DataType(DataType.Currency)] 
    [Display(Name = "Total Estimated Legal Cost")] 
    [DisplayFormat(DataFormatString = "£{0:#,###0.00}")] 
    public double EstimatedTotalLegalCost { get; set; } 
    public virtual ICollection<Overview> Overviews { get; set; } 
    public virtual ICollection<Process> Processes { get; set; } 
    public DateTime CreatedOn { get; set; } 
    public DateTime LastUpdated { get; set; } 
    public bool IsSelected { get; set; } 
    public bool IsDeleted { get; set; } 
} 
+0

什麼是您的賬戶模式? – py3r3str 2014-09-28 14:02:10

+0

好了,'付款'是用'virtual'關鍵字設置的 - >延遲加載被啓用。嘗試訪問'.Payments'導航屬性('var first = acc.Payments.FirstOrDefault()'),它應該從數據庫自動加載。 – 2014-09-28 14:28:53

+0

我把它改成了收費措施爲:(VAR firstPayment = acc.Payments.FirstOrDefault();),但它仍然被提出作爲無效:( – Dezzamondo 2014-09-28 14:37:16

回答

3

如果您查看實體框架生成的表,您會看到只有三個表。鑑於你的數據模型,應該有結表是AccountPayment對象映射到彼此(同樣爲PaymentProduct,並且你可能需要做你有其他收藏品一樣)。

你得到關於暫時無法投ProductsList到單個之一,是因爲你的數據模型顯示,Products是一個集合,但在數據庫表中實際存儲此爲外鍵(即單例外實體)PaymentProduct之間的關係。

如果我將OnModelCreating方法中的代碼更改爲以下代碼,您的AddProducts方法將按預期工作。

protected override void OnModelCreating(DbModelBuilder modelBuilder) 
{ 
    base.OnModelCreating(modelBuilder); 

    modelBuilder.Properties<DateTime>().Configure(c => c.HasColumnType("datetime2")); 

    modelBuilder.Entity<Account>().HasMany(x => x.Addresses) 
     .WithMany().Map(t => t.ToTable("AccountAddresses")); 
    modelBuilder.Entity<Account>().HasMany(x => x.Payments) 
     .WithMany().Map(t => t.ToTable("AccountPayments")); 
    modelBuilder.Entity<Payment>().HasMany(x => x.Products) 
     .WithMany().Map(t => t.ToTable("PaymentProducts")); 
    modelBuilder.Entity<Payment>().HasOptional(x => x.AccountID); 
    modelBuilder.Entity<Payment>().HasKey(x => x.PaymentID); 
} 

的變化是從代碼會像:

modelBuilder.Entity<Payment>().HasOptional(x => x.Products).WithMany(); 

要:

modelBuilder.Entity<Payment>().HasMany(x => x.Products).WithMany().Map(t => t.ToTable("PaymentProducts")); 

這樣做可以指示實體框架來創建聯結表,允許一個Payment持有的集合Products

+0

是的!!!謝謝!使用HasMany.WithMany去除HasOptional,並將它們映射到聯結表格就可以了! @nick_w謝謝你解決它:) – Dezzamondo 2014-10-03 07:47:48

+0

不客氣。快樂的編碼。 – 2014-10-03 07:50:01

0

當創建您的付款,你應該直接將其保存到數據庫。我不認爲將它添加到您的賬戶對象會起作用,因爲它是一個未被EF追蹤的實體。

public ActionResult AddProduct(List<Product> products) 
{ 
//var acc = Account.FetchAccountFromIdentity(User.Identity.GetUserName()); 
var username = User.Identity.GetUserName(); 
var acc = db.Accounts.First(u => u.EmailAddress == username); 
var payment = new Payment(); 

foreach (var product in products) 
{ 
    if (product.IsSelected) 
    { 
     var tempProduct = db.Products.Find(product.ProductID); 
     payment.Products.Add(tempProduct); 
     payment.PaymentStatus = enPaymentStatus.Pending; 
     payment.Gross += tempProduct.Price; 
     payment.Vat += tempProduct.Price * 0.2; 
     payment.Net += payment.Gross - payment.Vat; 
    } 
} 
payment.AccountID = acc.AccountID; 
db.Payments.Add(payment); 
db.SaveChanges(); 

return RedirectToAction("Pay", "Products", new {id = acc.AccountID}); 
} 
+0

誰投了我票,請你留下評論,並解釋爲什麼? – Shriike 2014-10-01 19:06:16

+0

最接近! @Sririike你的解決方案給出的錯誤:無法投射'System.Collections.Generic.List'1 [PPPv2.Models.Product]'類型的對象來鍵入'PPPv2.Models.Product'。當我們到達線db.Payments.Add(付款) – Dezzamondo 2014-10-01 19:40:45

+0

,我看到的產品列表是此行'payment.Products.Add(tempProduct)唯一的地方;'你可以嘗試評論說出來,看看你仍然可以得到同樣的錯誤?將產品的定義添加到消息中可能也很有幫助。 – Shriike 2014-10-01 19:53:10