繁体   English   中英

使用嵌套实体在实体框架中添加实体

[英]Adding an entity in Entity Framework with nested entities

尝试使用 Entity Framework 将实体添加到数据库时,我遇到了一个有趣的问题。 当我尝试向数据库添加新异常时,遇到以下错误:

“当 identity_insert 设置为关闭时,无法在表‘Notification’中为标识列插入显式值”

我猜这个错误是由于 Notification 实体已经有一个标识符(Id 属性)引起的。 但是,我的目标不是存储 Notification 实体。 碰巧我的 NotificationException 实体引用了现有的 Notification 实体。

如何在不遇到此问题的情况下正确更新我的 NotificationException 实体? 实际上关闭 identity_insert 似乎不是一个可行的解决方案。

我的两个 model 类:

public class Notification
{
    // Primary Key
    public long Id { get; set; }

    // Properties
    public bool IsSent { get; set; }
    public bool IsExpired { get; set; }
    public int RetryCount { get; set; }
    public int RetryTime { get; set; }
}

public class NotificationException
{
    // Primary Key
    public long Id { get; set; }

    // Properties
    public int Timestamp { get; set; }
    public string Exception { get; set; }

    // Foreign Keys
    public long NotificationId { get; set; }

    // Navigation Properties
    public virtual Notification Notification { get; set; }
}

流利的实体配置 API:

private void ConfigureNotificationEntity(EntityTypeBuilder<Notification> builder)
{
    builder.ToTable("Notifications");
    builder.HasKey(i => i.Id);

    builder.Property(i => i.Id)
        .IsRequired()
        .ValueGeneratedOnAdd();

    builder.HasMany(n => n.Exceptions)
        .WithOne(e => e.Notification)
        .OnDelete(DeleteBehavior.Cascade);
}

private void ConfigureNotificationExceptionEntity(EntityTypeBuilder<NotificationException> builder)
{
    builder.ToTable("NotificationExceptions");
    builder.HasKey(i => i.Id);
    builder.Property(i => i.Id)
        .IsRequired()
        .ValueGeneratedOnAdd();

    builder.HasOne(i => i.Notification)
        .WithMany(j => j.Exceptions);
}

主要问题:

public async Task<NotificationException> Add (NotificationException item)
{
    _context.NotificationExceptions.Add(item);
    await _context.SaveChangesAsync();
    return item;
}

一旦 _context.SaveChangesAsync(); 被调用,抛出上面提到的错误。

///编辑

我也用不同的对象测试了这个问题。 如果实体没有嵌套实体,那么存储它们就可以了。 该问题很可能与嵌套实体的已知 ID 有关。

所以事实证明,在 2016 年,EF Core 更改了 EF6 中 Attach 方法的行为: https://github.com/do.net/efcore/issues/4424

以机智:

  • 添加:添加尚未跟踪的每个可达实体
  • Attach :附加每个可达实体,除非可达实体具有存储生成的键且未分配键值,否则这些实体将被标记为已添加。

因此,解决方案只是改变
_context.NotificationExceptions.Add(item);
_context.NotificationExceptions.Attach(item);

这将添加没有密钥推送的新 NotificationException; 但是,带有已声明密钥的子通知将附加为“未更改”。

这个问题看起来像是你如何将通知 object 添加到你的 notificationException object 的问题。

像这样更改您的添加 function:

public async Task<NotificationException> Add (NotificationException item)
{
     var notification = _context.Notifications.Find( x => x.Id == yourNotificationId);
     item.Notification = notification;

    _context.NotificationExceptions.Add(item);
    await _context.SaveChangesAsync();
    return item;
}

这里的技巧是我们从相同的上下文中获得了通知实体,我们将添加 notificationException object。查看此链接以获取更多信息

找到修复方法!

var exception = new NotificationException()
{
    Exception = "Very serious exception!",
    QueuedNotificationId = notification.Id,// <-- setting the foreign key
    Timestamp = 420
};

我没有在异常实体中引用整个通知 object,而是设置了外键。 这样我就可以很好地存储实体。 EF 无法自动识别 Notification 实体已经存在的方式仍然有点愚蠢。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM