C# 实体中的主键与集合属性中的现有值冲突

C# 实体中的主键与集合属性中的现有值冲突,c#,entity-framework,C#,Entity Framework,我有以下几点: 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 Perso

我有以下几点:

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
}
我如何预防这个问题

编辑包含映射:

    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
    }

这是因为
映射
因为项目
合作伙伴
人员
中的所有实体都与上下文分离。。。请检查下面使用映射的正确方法。。。(这只是一个提示,不是完整的解决方案)


您还应该检查实体键的
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 
}
//GetAllProject返回IList
var projects=this.findProjectService.GetAllProjects();
foreach(项目中的var项目)
{
var projectDb=context.Project.Where(e=>e.Id==Project.Id).FirstOrDefault();
如果(projectDb==null)
{
//下一行将为您映射一个新项目以及每个合作伙伴中的所有合作伙伴和人员(如果找到)。。。
//因此,您将获得一些实体,这些实体应该附加到上下文中,以便ef注册,您的意思是不插入新的,而只是将它们映射到新项目
//var newProject=Mapper.Map(项目);
var newProject=context.Project.Create();
//您应该将映射设置为不映射ID,并让每个映射设置映射实体本身而不是其子实体
newProject=Mapper.Map(项目);
//循环项目模型中的所有合作伙伴
foreach(项目中的var合作伙伴。合作伙伴模型)
TopPartners(合作伙伴,newProject.Partners);
context.Project.Add(newProject);
SaveChanges();
}
}
public void TopPartners(PartnerModel模型、ICollection partners)
{
var partnerDb=context.Partner.Where(e=>e.Id==model.Id).FirstOrDefault();
if(parterDb==null)
{
var newPartner=context.Partner.Create();
newPartner=Mapper.Map(模型);
//循环合作伙伴模型中的所有人员
foreach(模型中的var person.PersonModel)
Toperson(个人、新合伙人、个人);
合伙人。添加(新合伙人);
}
其他的
{
//循环合作伙伴模型中的所有人员
foreach(模型中的var person.PersonModel)
Toperson(个人、合伙人、个人);
//在这里,合作伙伴被附加到上下文中,因此他不会插入新的上下文,而是将其添加(映射)到项目中。
添加(parterDb);
}
}
公共无效人员(人员模型、ICollection人员)
{
//地图
}

您能否显示自动映射器的映射设置和键的ef数据注释?您是否在保存更改之前检查了newProject.Partners中的
PersonId
ProjectId
?这些应该是默认值(null,0)或与数据库中的相同。@SherifAhmed yes,我包括在内mapping@nrodic不,我没有检查,因为项目是新的,但有时人或合作伙伴存在于数据库中。在我看来,
合作伙伴
-
项目
应该是多对多的。目前,与项目关联的合作伙伴只能属于该项目。
//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 
}