2015-06-08 77 views
2

我使用EF 6.1代碼第一,並試圖定義一個類發票的,可以由多個時間表實例的。從一個執行關聯到很多與代碼第一個實體框架

我想要做的是在數據庫中插入一個新的發票行,並且更新 Timesheet表,以便InvoiceId的外鍵從NULL更改爲新創建的Id發票。 不幸的是,正在發生的事情,而不是在於新行插入時間表表,而這些都與新生成的發票關聯。

我的類別是:

public class TimeSheet 
{ 
    public int Id { get; set; } 
    public DateTime WeekStart { get; set; } 
    public List<TimeSheetLine> TimeSheetLines { get; set; } 

    public int? InvoiceId { get; set; } 
    public virtual Invoice Invoice { get; set; } 
} 

public class Invoice 
{ 
    public int Id { get; set; } 
    public int? AgencyId { get; set; } 
    public int? ClientId { get; set; } 
    public int Rate { get; set; } 
    public Client Client { get; set; } 
    public Agency Agency { get; set; } 
    public List<TimeSheet> Timesheets { get; set; } 
} 

和映射類:

public class TimeSheetMap : EntityTypeConfiguration<TimeSheet> 
{ 
    public TimeSheetMap() 
    { 
     this.HasKey(x => x.Id); 
     this.ToTable("TimeSheet");      
     this.HasOptional(x => x.Invoice) 
      .WithMany(x => x.Timesheets) 
      .HasForeignKey(x => x.InvoiceId); 
    } 
} 

編輯 代碼來構建發票對象:

public bool GenerateInvoice(InvoiceVM invoice) 
    { 
     //create an Invoice record from the InvoiceVM 
     Invoice inv = new Invoice(); 
     List<TimeSheet> sheets = new List<TimeSheet>(); 

     foreach (var item in invoice.TimesheetList) 
     { 
      TimeSheet ts = manager.GetTimesheetById(item.Id); 
      sheets.Add(ts); 
     } 
     inv.Timesheets = sheets; 

     //save the invoice 
     manager.GenerateInvoice(inv); 
     return true; 
    } 

編輯2毫安nager class

 public bool GenerateInvoice(Invoice invoice) 
    { 
     bool ret = false; 
     using (DataContext dc = new DataContext()) 
     { 
      dc.Invoices.Add(invoice); 
      dc.SaveChanges(); 
      ret = true; 
     } 

     return ret; 
    } 

任何明顯的變化,我可以讓這個工作?

+2

你可以在哪裏做代碼發票對象的實際創建? –

+1

聽起來像您正在使用的TimeSheets不是來自數據庫(換句話說,沒有附加到上下文) – tschmit007

+0

已添加發票對象創建代碼。它保存時肯定有正確的時間表ID。 – jazza1000

回答

1

看來好像你正在使用一個上下文從數據庫和一個單獨的上下文保存發票拉你的發票。該DataContextGenerateInvoice函數內部不知道TimeSheets已經在數據庫中,因爲它們是由不同的上下文檢索,在manager.GetTimesheetById(item.Id);

有,你可以處理這個過程中的一些方法,這裏有兩個選項:

  1. 執行您的查找和附件內manager.GenerateInvoice(),而不是視圖模型內。這將是最乾淨的方法,但需要經理處理時間表。即:

    Public bool GenerateInvoice(Invoice invoice, List<TimeSheet> timesheets) 
    { 
        bool ret = false; 
        using (DataContext dc = new DataContext()) 
        { 
         foreach (var item in timesheets) 
         { 
          TimeSheet ts = dc.GetTimesheetById(item.Id); 
          invoice.TimeSheets.Add(ts); 
         } 
         dc.Invoices.Add(invoice); 
         dc.SaveChanges(); 
         ret = true; 
        } 
        return ret; 
    } 
    
  2. 執行兩個獨立的數據庫調用,一個插入一個Invoice,返回發票Id,第二更新時間表。

    public int GenerateInvoice(Invoice invoice) 
    { 
        using (DataContext dc = new DataContext()) 
        { 
         dc.Invoices.Add(invoice); 
         dc.SaveChanges(); 
        } 
        return invoice.Id; 
    } 
    
    public bool GenerateInvoice(InvoiceVM invoice) 
    { 
        //create an Invoice record from the InvoiceVM 
        Invoice inv = new Invoice(); 
        //handle other fields for invoice here 
    
        //create invoice, with no timesheets 
        int invoiceId = manager.GenerateInvoice(inv); 
    
        //loop through the timesheets and assign the invoice to them. 
        using (DataContext dc = new DataContext()) 
        { 
         foreach (var item in invoice.TimesheetList) 
         { 
          TimeSheet ts = dc.GetTimesheetById(item.Id); 
          ts.InvoiceId = invoiceId; 
         } 
         dc.SaveChanges(); 
        } 
        return true; 
    } 
    

你可能需要重構這兩種解決方案,以滿足您的全域模型,但希望這些方法可以把你在正確的方向。

+0

我在你的選項2上使用了一個變體來做到這一點,datacontext必須是與保存數據一樣的數據,所以我將GetTimeSheetById的代碼放入了直流保存它。 – jazza1000

0

從根本上說這裏的問題是我在每個存儲庫方法

using (DataContext dc = new DataContext()) 

這意味着,對象追蹤是完全迷失在這樣做。根據我的經驗,我不會推薦這樣做。

我已經移動到一個模塊級的DbContext代替,其可用於組操作進入工作單元。只要我這樣做了,所有生成的SQL就開始工作,就像我認爲它應該一樣,相關實體在數據庫中正確更新。

相關問題