我正在使用流畅的语法来配置简单Movie
和Genre
实体之间的M:M关系。那工作正常。
我的问题是我也希望将链接/连接表MovieGenre
公开为实体。我意识到它没有必要,因为它只包含键,但我希望它能够实现,因为它会使操作变得更容易。
当我尝试配置链接表时出现此错误:
具有架构'Media'和表'MovieGenre'的EntitySet'MovieGenre1' 已经定义了。
我知道我必须设置M:M关系,但还没弄明白如何让它们全部协同工作。
以下是我的代码:
public class Genre
{
public int GenreID { get; set;}
public string Name { get; set; }
public ICollection<Movie> Movies { get; set; }
}
public class Movie
{
public int MovieID { get; set; }
public string Title { get; set; }
public ICollection<Genre> Genres { get; set; }
}
public class MovieGenre
{
public int MovieID { get; set; }
public int GenreID { get; set; }
public Movie Movie { get; set; }
public Genre Genre { get; set; }
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
//Genre
modelBuilder.Entity<Genre>()
.ToTable("Genre", "Media");
//Movie
var movieCfg = modelBuilder.Entity<Movie>();
movieCfg.ToTable("Movie", "Media");
movieCfg.HasMany(m => m.Genres)
.WithMany(g => g.Movies)
.Map(m =>
{
m.MapLeftKey("MovieID");
m.MapRightKey("GenreID");
m.ToTable("MovieGenre", "Media");
});
//MovieGenres
var movieGenresCfg = modelBuilder.Entity<MovieGenre>();
movieGenresCfg.ToTable("MovieGenre", "Media");
movieGenresCfg.HasKey(m => new
{
m.MovieID, m.GenreID
});
base.OnModelCreating(modelBuilder);
}
任何帮助将不胜感激。谢谢。
答案 0 :(得分:6)
你正在尝试的是不可能的。您需要从映射中删除MovieGenre。
不要担心从数据库中获取实体只是为了将它添加到Genres列表中。如果您通过id多次加载实体,则无论如何只有一次调用DB。随着EF变得更好并且添加了二级缓存,它将正常工作并且运行良好。如果你太迫切需要,那么框架就没有任何魔力。
如果您考虑模型的域和用户,那么大多数都是读取,因此没有太多更新。除此之外,将一部电影添加到一个类型或反过来可能意味着许多事情,在这种情况下,你不应该直接公开集合,而是添加方法来实现行为。
行为的一个例子是“如果你将电影添加到超过10种类型,那么电影应该将其类别改为X”以及各种其他事物。不要再考虑数据了。 Domain Driven Design是一本关于这个主题的好书。
在这种情况下,您可以将Movie实体视为根聚合,因为电影是您的用户所追求的,而电影是您要以管理员身份编辑的内容。也许,电影可以在没有流派的情况下存在,因此流派只是电影上的标签,价值对象,并不是非常重要。你的映射将成为:
public class Genre
{
public int GenreID { get; set;}
public string Name { get; set; }
}
public class Movie
{
public int MovieID { get; set; }
public string Title { get; set; }
public ICollection<Genre> Genres { get; set; }
}
....
//Movie
var movieCfg = modelBuilder.Entity<Movie>();
movieCfg.ToTable("Movie", "Media");
movieCfg.HasMany(m => m.Genres)
.WithMany()
.Map(m =>
{
m.MapLeftKey("MovieID");
m.MapRightKey("GenreID");
m.ToTable("MovieGenre", "Media");
});
查询看起来像:
// get all movies for a particular genre
var movies = movieContext.Movies.Where(m => m.Genres.Any(g => g.GenreID = id))
.OrderBy(m => m.Name)
.ToList();
// get all movies
var movies = movieContext.Movies.OrderBy(m => m.Name).Take(10).ToList();
这几乎与您的域名有关。