2015-06-08 40 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就开始工作,就像我认为它应该一样,相关实体在数据库中正确更新。

相关问题