2016-08-07 182 views
0

我正在使用实体框架(6.1.3)和代码优先方法。我有一个模型类电影和模型类标签看起来像这样:多对多关系 - 实体框架正在创建新对象

public class Movie 
{ 
    public int Id { get; set; } 
    public string Name { get; set; } 
    public ICollection<Tag> Tags { get; set; } 
} 

public class Tag 
{ 
    public int Id { get; set; } 
    public string Name { get; set; } 
} 

在的DbContext我改写OnModelCreating方法来建立这样一个一对多的关系:

protected override void OnModelCreating(DbModelBuilder modelBuilder) 
{ 
    modelBuilder.Entity<Movie>() 
       .HasMany(a => a.Tags) 
       .WithMany() 
       .Map(x => 
       { 
        x.MapLeftKey("Movie_Id"); 
        x.MapRightKey("Tag_Id"); 
        x.ToTable("MovieTags"); 
       }); 

    base.OnModelCreating(modelBuilder); 
} 

如果我尝试使用某些标签将影片插入数据库,我遇到了创建不需要的标签的问题。

例如,我已经在数据库中有两个标签“Foo”(Id:1)和“Bar”(Id:2)。现在我创建一个新的Movie对象,并将现有标签“Foo”(从数据库加载)和新标签“Foobar”插入到对象的集合中。将此影片添加到DbContext并调用方法“SaveChanges”后,我的数据库中有两个新标签。

为什么实体框架为我的数据库插入一个存在的标签?我必须改变什么,只有缺失的标签被插入?

编辑-1: 这里是控制器代码,我添加了标签,并将其保存

List<Tag> tagList = new List<Tag>(); 
// ViewModel.Tags either contains the Tag-Id or the Tag-Name (if it is new) 
foreach (string tag in viewModel.Tags) 
{ 
    if (IsDigitsOnly(tag)) 
    { 
     // Load the existing Tag from the DbContext and add to List 
     tagList.Add(TagService.Get(int.Parse(tag))); 
    } 
    else 
    { 
     // Create new Tag 
     tagList.Add(new Tag() { Name = tag }); 
    } 
} 

Movie movie = new Movie(); 
movie.Name = viewModel.Name; 
movie.Tags = tagList; 

MovieService.Insert(movie); 

这里是与刀片

public void Insert(Movie movie) 
{ 
    Context.Movie.Add(movie); 
    Context.SaveChanges(); 
} 

编辑-2 MovieService码: 我发现问题了!这是我如何设置我的项目的一个问题。我使用Ninject进行DI,并且没有将DbContext绑定到请求(InRequestScope)。所以每次我的一个服务被调用时,它都会使用不同的DbContext,因为它不知道已经加载了标签。

+0

你能否纠正帖子标题 - 你在做什么是多对多的关系。 –

+0

是的,我改变了。我不知道我为什么写“一对多”。我知道这是很多很多... – Shamshiel

回答

0

您可以提供代码添加标签的位置吗?

在此期间,我以为这是类似

Movie.Tags.Add(new Tag { Name = "foo" }); 

你可能会想,如下所示添加现有标签:

Movie.Tags.Add(ctx.Tags.First(T => T.Name == "foo")); 

...或等效的代码,将得到来自您的上下文的标签。

此外,您可能希望使标签ICollection虚拟,以便代理可以覆盖它。这可能也是一个很难找到的错误来源。

+0

我编辑我的原始问题,我如何添加标签。但是现在我发现了这个问题,我也将它添加到了我原来的问题中。 – Shamshiel

+0

太好了。祝你好运。 – DPH