2015-10-24 45 views
1

我有這樣的實體:衝突在集合屬性與現有的價值實體PRIMARY KEY的

public class Partner 
{ 
    public string ID { get; set; } 
    public string Name { get; set; } 
    public string PersonId { get; set; } 
    public int ProjectId { get; set; } 

    #region Navigation Properties 

    public virtual Person Person { get; set; } 
    public virtual Project Project { get; set; } 

    #endregion 
} 

public class Person 
{ 
    public string ID { get; set; }  
    public string Username { get; set; } 

    #region Navigation Properties 

    public virtual ICollection<Partner> Partners { get; set; } 

    #endregion 
} 

public class Project 
{   
    public int ID { get; set; } 
    public string Name { get; set; } 
    public DateTime DateStart { get; set; } 
    public DateTime DateEnd { get; set; } 
    public string Client { get; set; } 

    #region Navigation Properties 

    public ICollection<Partner> Partners { get; set; } 

    #endregion 
} 

當我插入一個新的項目,我在Partners財產(Project類)現有的合作伙伴,或者Person財產(Partner類)現有人員。發生這種情況時,會發生「違反主密鑰」的例外情況。

我的代碼SABE Projects是這樣的:

//GetAllProject return IList<ProjectModel> 
var projects = this.findProjectService.GetAllProjects(); 

foreach(var project in projects) 
{ 
    var projectDb = context.Project.Where(e => e.Id == project.Id).FirstOrDefault(); 

    if (projectDb == null) 
    { 
     logger.Debug("Try add new project {0}", project.Name); 
     var newProject = Mapper.Map<ProjectModel, Project>(project); 
     context.Project.Add(newProject); 
     context.SaveChanges(); 
    } 
} 

我如何避免這個問題?

編輯爲包括映射:

internal PartnerMap() 
    { 
     // Primary Key 
     this.HasKey(t => t.Id); 

     // Properties 
     this.Property(t => t.Id) 
      .IsUnicode(false); 

     this.Ignore(t => t.Name); 

     this.Property(t => t.PersonId) 
      .IsUnicode(false); 

     // Table 
     this.ToTable("Partner"); 

     // Relations 
     this.HasRequired(t => t.Project) 
      .WithMany(r => r.Partners) 
      .HasForeignKey(t => t.ProjectId) 
      .WillCascadeOnDelete(false); 

     this.HasRequired(t => t.Person) 
      .WithMany(r => r.Partners) 
      .HasForeignKey(t => t.PersonId) 
      .WillCascadeOnDelete(false); 
    } 

    internal PersonMap() 
    { 
     // Primary Key 
     this.HasKey(t => t.Id); 

     // Properties 
     this.Property(t => t.Id) 
      .IsUnicode(false); 

     this.Ignore(t => t.Username); 

     // Table 
     this.ToTable("Person"); 

     // Relations 
    } 

    internal ProjectMap() 
    { 
     // Primary Key 
     this.HasKey(t => t.Id); 

     // Properties 
     this.Property(t => t.Name) 
      .IsUnicode(false); 

     this.Property(t => t.Client) 
      .IsUnicode(false); 

     // Table 
     this.ToTable("Project"); 

     // Relations 
    } 
+0

你能展示automapper的映射設置和key的ef數據註解嗎? –

+0

您是否在SaveChanges之前檢查newProject.Partners中的'PersonId'和'ProjectId'?這些應該是默認值(null,0)或者與數據庫中的相同。 – nrodic

+0

@SherifAhmed是的,我包括映射 –

回答

1

這是因爲mapping的,因爲所有的項目Partners & Persons從上下文中分離的實體......請通過下面的正確方法使用映射...(這只是一個暗示不是完整的解決方案)


你還應該檢查DatabaseGeneratedOption爲你的實體鍵使他們成爲Identity或者你必須提交每個插入。

//GetAllProject return IList<ProjectModel> 
var projects = this.findProjectService.GetAllProjects(); 

foreach(var project in projects) 
{ 
    var projectDb = context.Project.Where(e => e.Id == project.Id).FirstOrDefault(); 

    if (projectDb == null) 
    { 
     // the next line will map you a newproject and all of the partners and persons inside the each parnter if found ... 
     // so you will get some entities which should be attached to the context in order for the ef to regonise that you mean not to insert new, but just to map them to the new project .. so 
     //var newProject = Mapper.Map<ProjectModel, Project>(project); 

     var newProject = context.Project.Create(); 
     // you should setup your mapping to not map the ID and let each mapsetup to map an entity itself not it's child entities 
     newProject = Mapper.Map<ProjectModel, Project>(project); 

     // loop all partners in the PROJECT MODEL 
     foreach(var partner in project.PartnerModels) 
      ToPartners(partner, newProject.Partners); 

     context.Project.Add(newProject); 
     context.SaveChanges(); 
    } 
} 

public void ToPartners(PartnerModel model, ICollection<Partner> partners) 
{ 
    var partnerDb = context.Partner.Where(e => e.Id == model.Id).FirstOrDefault(); 
    if(parterDb == null) 
    { 
     var newPartner = context.Partner.Create(); 
     newPartner = Mapper.Map<PartnerModel, Partner>(model); 

     // loop all persons in the PARTNER MODEL 
     foreach(var person in model.PersonsModel) 
      ToPersons(person, newPartner.Persons); 

     partners.Add(newPartner); 
    } 
    else 
    { 
     // loop all persons in the PARTNER MODEL 
     foreach(var person in model.PersonsModel) 
      ToPersons(person, partnerDb.Persons); 

     // here the partner is attached to the context so he will not insert a new one, it will just add (map) it to the project. 
     partners.Add(parterDb); 
    } 
} 

public void ToPersons(PersonModel model, ICollection<Person> persons) 
{ 
    // MAP IT 
}