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

相關問題