0

我需要在我的数据库的2表中插入一行。这两张表之间的关系是一对多关系。这是他们模式自动生成id时如何使用entiity Framework core插入数据?

public partial class Task 
{ 
    public Task() 
    { 
     TaskOwner = new HashSet<TaskOwner>(); 
    } 

    public int Id { get; set; } 
    public string Action { get; set; } 
    public int ActualEffort { get; set; } 
    public DateTime AssignationDate { get; set; } 
    public int EstEffort { get; set; } 
    public DateTime EstEnd { get; set; } 
    public bool IsComplete { get; set; } 
    public int ProjectId { get; set; } 
    public string Status { get; set; } 

    public virtual ICollection<TaskOwner> TaskOwner { get; set; } 
    public virtual Project Project { get; set; } 
} 

public partial class TaskOwner 
{ 
    public int Id { get; set; } 
    public int EmployeId { get; set; } 
    public int TaskId { get; set; } 

    public virtual Employe Employe { get; set; } 
    public virtual Task Task { get; set; } 
} 

这是背景

modelBuilder.Entity<Task>(entity => 
     { 
      entity.HasIndex(e => e.ProjectId) 
       .HasName("FKTask25514"); 

      entity.Property(e => e.Id) 
       .HasColumnName("id") 
       .HasColumnType("int(10)"); 

      entity.Property(e => e.Action) 
       .IsRequired() 
       .HasColumnName("action") 
       .HasColumnType("varchar(255)"); 

      entity.Property(e => e.ActualEffort) 
       .HasColumnName("actual_effort") 
       .HasColumnType("int(10)"); 

      entity.Property(e => e.AssignationDate).HasColumnName("assignation_date"); 

      entity.Property(e => e.EstEffort) 
       .HasColumnName("est_effort") 
       .HasColumnType("int(10)"); 

      entity.Property(e => e.EstEnd).HasColumnName("est_end"); 

      entity.Property(e => e.IsComplete).HasColumnType("tinyint(1)"); 

      entity.Property(e => e.ProjectId) 
       .HasColumnName("project_id") 
       .HasColumnType("int(10)"); 

      entity.Property(e => e.Status) 
       .IsRequired() 
       .HasColumnName("status") 
       .HasColumnType("varchar(255)"); 

      entity.HasOne(d => d.Project) 
       .WithMany(p => p.Task) 
       .HasForeignKey(d => d.ProjectId) 
       .OnDelete(DeleteBehavior.Restrict) 
       .HasConstraintName("FKTask25514"); 
     }); 

     modelBuilder.Entity<TaskOwner>(entity => 
     { 
      entity.ToTable("Task_Owner"); 

      entity.HasIndex(e => e.EmployeId) 
       .HasName("FKTask_Owner320287"); 

      entity.HasIndex(e => e.TaskId) 
       .HasName("FKTask_Owner395416"); 

      entity.Property(e => e.Id) 
       .HasColumnName("id") 
       .HasColumnType("int(10)"); 

      entity.Property(e => e.EmployeId) 
       .HasColumnName("employe_id") 
       .HasColumnType("int(10)"); 

      entity.Property(e => e.TaskId) 
       .HasColumnName("task_id") 
       .HasColumnType("int(10)"); 

      entity.HasOne(d => d.Employe) 
       .WithMany(p => p.TaskOwner) 
       .HasForeignKey(d => d.EmployeId) 
       .OnDelete(DeleteBehavior.Restrict) 
       .HasConstraintName("FKTask_Owner320287"); 

      entity.HasOne(d => d.Task) 
       .WithMany(p => p.TaskOwner) 
       .HasForeignKey(d => d.TaskId) 
       .OnDelete(DeleteBehavior.Restrict) 
       .HasConstraintName("FKTask_Owner395416"); 
     }); 

一个任务可以由多个TaskOwner拥有。我想这个计算策略:

Models.Task task = new Models.Task() 
        { 
         Status = tde.Status.ToString(), 
         Action = tde.Subject.ToString(), 
         IsComplete = tde.IsComplete, 
         EstEnd = tde.DueDate.GetValueOrDefault(DateTime.Now), 
         AssignationDate = tde.DateTimeCreated.Date, 
         ActualEffort = Convert.ToInt32(tde.ActualWork), 
         EstEffort = Convert.ToInt32(tde.TotalWork), 
         ProjectId = (from p in _context.Project 
            where p.ProjectSapId == Convert.ToInt32(tde.BillingInformation) 
            select p.Id).First(), 
        }; 

        Models.TaskOwner taskOwner = new Models.TaskOwner() 
        { 
         EmployeId = employee.Id, 
        }; 
        task.TaskOwner.Add(taskOwner); 
        _context.Task.Add(task); 

然后将其保存到数据库中,但我总是revieve此错误:

self referencing loop detected with type 'Models.TaskOwner' . Path '[6].taskOwner[0].employe.taskOwner'.

如果我可以,我只想用我刚刚任务的ID创建并链接到taskOwner模型,但由于ID是自动生成的我不能或至少我不知道如何。我究竟做错了什么?什么是我正在努力完成的正确方法?

回答

1

所以,一个Task有零或更多TaskOwners。每个TaskOwner只有一个Task。没有TaskOwners没有Task

这意味着,如果您在数据库中有现有的TaskOwner,则不能再拥有第二个Task。但是你可以让它拥有一个不同的Task而不是它现在拥有的那个。

如果向与数据库中的现有对象具有关系的数据库引入(添加)对象,则可以使用相关对象的Id或对象本身(当然,零Id)。

如果相关对象也是新建的,只需将相关对象分配给要添加的对象。您将不必分别添加相关对象。

请注意,只要您没有使用SaveChanges,就不能使用任何新对象的Id。

介绍一个TaskOwner拥有现有任务和现有雇员

using (var dbContext = new MyDbContext()) 
{ 
    int employeeId = FetchEmployeeId(...); 
    int taskId = FetchTaskId(...); 

    TaskOwner introducedTaskOwner = dbContext.TaskOwners.Add(new TaskOwner() 
    { 
     // don't fill the ID! 
     EmployeeId = employeeId, 
     TaskId = taskId, 

     ... // other properties 
    }); 
    dbContext.SaveChanges(); 

    // now the introduced task owner has an Id! 
    return introducedTaskOwner; 
} 

一起引入一个TaskOwner用新的任务。利用现有的员工

现在,你可以不填的任务id,而不是填补了任务:如果你愿意,你可以先介绍一下任务,然后TaskOwner

using (var dbContext = new MyDbContext()) 
{ 
    int employeeId = FetchEmployeeId(...); 

    TaskOwner introducedTaskOwner = dbContext.TaskOwners.Add(new TaskOwner() 
    { 
     // don't fill the TaskOwner ID! 
     EmployeeId = employeeId, 

     // Give the Task owner a non-existing Task: 
     Task = new Task() 
     { 
      // don't fill the Task ID! 
      // don't fill the collection of TaskOwners 

      ... // fill other Task properties 
     } 

     ... // other task owner properties 
    }); 
    dbContext.SaveChanges(); 

    // now both the task owner and the task are introduced. Both have an ID 
    Debug.Assert(introducedTaskOwner.Id != 0); 
    Debug.Assert(intrducedTaskOwner.TaskId != 0); 
    Debug.Assert(introducedTaskOwner.Task.Id != 0); 
} 

。只要你没有使用SaveChanges,你就不能使用任何Id。

using (var dbContext = new MyDbContext()) 
{ 
    int employeeId = FetchEmployeeId(...); 

    Task introducedTask = dbContext.Tasks.Add(new Task() 
    { 
     // don't fill the Task ID! 
     TaskOwners = new List<TaskOwner>(); // This Task has no owners yet 

      ... // fill other Task properties 
    }); 

    TaskOwner introducedTaskOwner = dbContext.TaskOwners.Add(new TaskOwner() 
    { 
     // don't fill the TaskOwner ID! 
     EmployeeId = employeeId, 

     // Give the Task owner a the introduced task 
     Task = introducedTask, 

     ... // other task owner properties 
    }); 
    dbContext.SaveChanges(); 
} 

你也可以做它的其他方式轮:你可以一个TaskOwner添加到现有(或新加入的)任务

using (var dbContext = new MyDbContext()) 
{ 
    int employeeId = FetchEmployeeId(...); 

    // get existing task: 
    Task existingTask = dbContext.Tasks 
     .Where(task => task.ActualEffort > ...) 
     .OrderBy(task => task.ActualEffort) 
     .FirstOrDefault(); 

    // add an owner to the task owners collection: 
    existingTask.TaskOwners.Add(new TaskOwner() 
    { 
     // don't fill the TaskOwner ID! 
     EmployeeId = employeeId, 
     // no need to fill the TaskId, nor the Task 
     // Entity Framework knows the Task to which it belongs, because you 
     // add it to the TaskOwners collection 
     ...   
    }); 
    dbContext.SaveChanges(); 
} 

结论:只要你没有一个Id ,使用完整的对象。如果对象尚未添加,实体框架将添加它

+0

非常感谢!随着你的回答,我意识到我在BD的结构中犯了一个错误。它现在工作完美! –

0

首先您需要保存Models.Task并访问自动生成的ID,然后保存TaskOwner模型。

+0

没有更好的方法,我不需要在数据库中为每个任务添加一次调用两次?我已经读过,保存是一个非常昂贵的电话。 –

+0

我仍然收到错误信息,即使双保存... –

+0

@ MarcelJr.SamsonMorasse出现了一些东西,所以无法给你正确的答案。很好,你找到了一个解决方案。干杯。 – summerGhost

相关问题