多对多关系 - 实体框架正在创建新对象

时间:2016-08-07 12:07:07

标签: c# entity-framework

我使用实体框架(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);
}

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

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

为什么实体框架会在我的数据库中插入现有标签?我需要更改只插入缺少的标签吗?

修改-1: 这是Controller代码,我在其中添加标签并保存

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);

以下是带有插入

的MovieService代码
public void Insert(Movie movie)
{
    Context.Movie.Add(movie);
    Context.SaveChanges();
}

修改-2: 我发现了问题!这是我设置项目的一个问题。我使用Ninject进行DI,我没有将DbContext绑定到请求(InRequestScope)。因此,每次调用我的一个服务时,它都使用不同的DbContext,因此它不知道已加载的标签。

1 个答案:

答案 0 :(得分:0)

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

与此同时,我认为它类似于

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

您可能希望添加现有标记,如下所示:

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

...或从您的上下文中获取Tag的等效代码。

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