使用集合属性中的现有值违反实体中的PRIMARY KEY

时间:2015-10-24 19:50:26

标签: 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 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类)现有人员。发生这种情况时,会发生“违反PRIMARY KEY”的异常。

我的代码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
    }

1 个答案:

答案 0 :(得分:1)

这是因为mapping,因为项目中的所有实体Partners&amp; 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 
}