简体   繁体   中英

Entity Framework 1 to Many creates new objects

I'm using EntityFramework for my Microsoft Sql Data Base. First entity is Product :

 public class Product
{
    public Product()
    {
        ProductStories = new HashSet<ProductStory>();
    }

    public int ProductId { get; set; }

    public string Name { get; set; }

    public string Description { get; set; }

    public bool Deleted { get; set; }

    public HashSet<ProductStory> ProductStories { get; set; }
}

And another entity is ProductStory , which stores story about income or outcome of Products .

public class ProductStory
{
    public int ProductStoryId { get; set; }

    public virtual Product.Product Product { get; set; }

    public int Count { get; set; }

     public DateTime DateTime { get; set; }
}

So one Product could be in mane ProductStories , or in none.

I will not show all code(too big), so when I firstly create a single Product instance and save it in DB. Then I create a single ProductStory and reference to property Product to that instance of Product. Then I save this ProductStory , there becomes 2 instances of ProductStory . As I read, and I made this as virtual property:

public virtual Product.Product Product { get; set; }

How this problem could be solved?

I'm using EntityTypeConfiguration for tables configuration.

public class ProductMap : EntityTypeConfiguration<Product>
    {
        public ProductMap()
        {
            ToTable("Products").HasKey(x => x.ProductId);

            Property(x => x.ProductId).IsRequired();
            Property(x => x.Name).IsRequired().HasMaxLength(255).HasColumnName("Name");
                //.HasColumnAnnotation("Index", new IndexAnnotation(new IndexAttribute("IX_Name") { IsUnique = true }));
            Property(x => x.Description).IsOptional().HasColumnName("Description");
            Property(x => x.Deleted).HasColumnName("Deleted");
        }
    }

And for ProductStory:

class ProductStoryMap: EntityTypeConfiguration<ProductStory>
    {
        public ProductStoryMap()
        {
            ToTable("ProductStories").HasKey(ps => ps.ProductStoryId);

            Property(ps => ps.ProductStoryId).IsRequired();
            //Property(ps => ps.ProductId).IsRequired().HasColumnName("ProductId");

            Property(ps => ps.Count).HasColumnName("Count");
            Property(ps => ps.DateTime).HasColumnName("DateTime");
        }
    }

You have some errors in your code:

//Change this:
public HashSet<ProductStory> ProductStories { get; set; }
//For this (virtual is needed here, also use ICollection rather than any specific implementation)
public virtual ICollection<ProductStory> ProductStories { get; set; }

//Change this:
public virtual Product.Product Product { get; set; }
//For this (virtual makes no sense here)
public Product.Product Product { get; set; }

And lastly, ProductStory needs a way to keep the reference to its parent Product . This is what creates the Foreign Key relationship in your database and allows Entity Framework to link the tables. So add this to ProductStory :

public int ProductId { get; set; }

If you are still getting a duplicated object (which may happen), ensure you are setting the ProductId to the ProductStory you are saving.

The solution was about Entity Framework "bug/feature". As I add new ProductStory into DataBase, it attaches the whole graph(including all other entities references and recreates them). So before commiting new ProductStory , I have to set to null all it's navigation properties to avoid recreating.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM