【问题标题】:How to avoid adding duplicate records in the database with Entity Framework Code First and Web API?如何避免使用 Entity Framework Code First 和 Web API 在数据库中添加重复记录?
【发布时间】: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


【解决方案1】:

复合键是个好主意,可以看作是更好的数据库设计,因为 AlbumID 和 SongID 是真正将记录标识为唯一的。

EF 提供并发检查,除了更新模型和在 else 语句中添加 try/catch 之外,不需要进行很多更改。 This article 可以带您完成整个过程,但会在您的数据库中添加一个字段。 This article 使用并发检查,但不向数据库添加字段。

【讨论】:

  • 感谢您的回复和有用的链接。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-12-24
相关资源
最近更新 更多