【发布时间】:2015-03-19 15:41:27
【问题描述】:
我的 Web 应用程序是使用 MVC 和 Entity Framework Code First 构建的。为了解释我的问题,我用一个简化的专辑 - 歌曲示例来描述它:
public abstract class MusicStoreEntity
{
[Display(AutoGenerateField = false), Key, Required, Column(Order = 0)]
public Guid Id { get; set; }
}
[Table(TableName), DataContract]
public class Album : MusicStoreEntity
{
public const string TableName = "Albums";
public virtual Collection<AlbumSong> Songs { get; set; }
}
[Table(TableName), DataContract]
public class Song : MusicStoreEntity
{
public const string TableName = "Songs";
public virtual Collection<AlbumSong> Albums { get; set; }
}
这两个实体通过一个包含两个外键和一个唯一标识符的单独实体多对多连接:
[Table(TableName), DataContract]
public class AlbumSong : MusicStoreEntity
{
public const string TableName = "AlbumSongs";
[DataMember, Required]
public Guid AlbumId{ get; set; }
public virtual Album Album { get; set; }
[DataMember, Required]
public Guid SongId { get; set; }
public virtual Song Song { get; set; }
}
通过传入的 API 调用,如果两个实体尚未连接,您可以创建一个新实体:
public void SetAlbumSong(Guid albumId, Guid songId) {
var albumSong = DBContext.Set<AlbumSong>().SingleOrDefault(a => a.AlbumId == albumId && a.SongId == songId);
if(albumSong == null) {
var albumSong = new AlbumSong {
AlbumId = albumId,
SongId = songId
}
DBContext.Set<AlbumSong>().Add(albumSong);
DBContext.SaveChanges();
} else {
// update existing albumSong
}
}
但是,当两个 API 调用几乎同时进入且具有相同的实体 ID 时,会有一个窗口允许在同一张专辑和歌曲之间添加两个 AlbumSong 实体。
一种解决方案是制作一个Composite Key,它包含AlbumSong 实体中的两个外来ID。这样就不能制作两个重复的 AlbumSong 并且会抛出异常。
一个类似的解决方案是向 AlbumSong 添加一个额外的属性,该属性结合了两个 id 并要求列是唯一的。
但是,我想知道是否有其他(更好、更清洁)的解决方案来解决这个问题,因为上述解决方案会为我的特定应用程序带来不必要的变化。
(我的 Web 应用程序是使用 MVC 4 和 Entity Framework 5 构建的。)
【问题讨论】:
-
如果你在这个实体上有一个复合键......如果另一个表有这个表的 FK,你必须把两列都带上。这就是为什么我倾向于对复合键使用唯一约束。
-
更好,更干净...这是高度基于意见的。如果复合键对您当前的应用程序造成问题,我会选择唯一索引和单数主键。
标签: c# entity-framework asp.net-mvc-4 entity-framework-5