【问题标题】:Many to Many Relationship - Entity Framework is creating new objects多对多关系 - 实体框架正在创建新对象
【发布时间】:2016-08-07 12:07:06
【问题描述】:

我正在使用实体框架 (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”后,我的数据库中有两个新标签。

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

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

这是带有插入的 MovieService 代码

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

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

【问题讨论】:

  • 能否请您更正帖子标题 - 您在讨论的是多对多关系。
  • 是的,我改了。我不知道我为什么写“一对多”。我知道这是多对多...

标签: c# entity-framework


【解决方案1】:

您能否提供添加标签的代码?

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

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

您可能希望按如下方式添加现有标签:

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

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

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

【讨论】:

  • 我用如何添加标签编辑了我的原始问题。但我现在发现了问题,我也将它添加到我原来的问题中。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-10-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-01-28
  • 2011-12-17
相关资源
最近更新 更多