gpt4 book ai didi

entity-framework-4.1 - 在 EF 代码中删除首先会导致导航属性设置为 null 和空

转载 作者:行者123 更新时间:2023-12-05 00:03:36 24 4
gpt4 key购买 nike

当我首先使用 EF 代码执行删除时,我注意到一些有趣的事情。我使用以下域模型:

public class User
{
public virtual long Id { get; set; }
public virtual string Name { get; set; }
public virtual ICollection<Playlist> Playlists { get; set; }
}

public class Playlist
{
public virtual long Id { get; set; }
public virtual string Title { get; set; }
public virtual User User { get; set; }
public virtual ICollection<Track> Tracks { get; set; }
}

public class Track
{
public virtual long Id { get; set; }
public virtual string Title { get; set; }
public virtual Playlist Playlist { get; set; }
}

模型配置使用:
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<User>().HasMany(x => x.Playlists).WithRequired(x => x.User).Map(x => x.MapKey("UserId"));
modelBuilder.Entity<Playlist>().HasMany(x => x.Tracks).WithRequired(x => x.Playlist).Map(x => x.MapKey("PlaylistId"));
}

我使用通用存储库:
public virtual void Delete(T entity)
{
Database.Set<T>().Remove(entity);
}

我还有一个 dto 看起来像:
public class PlaylistDTO
{
public PlaylistDTO(Playlist playlist)
{
Id = playlist.Id;
Title = playlist.Title;
User = playlist.User.Name;
}
}

在我的一项服务中,我正在尝试执行以下操作:
public PlaylistDTO Delete(long id)
{
Playlist playlist = playlistRepository.GetById(id);
playlistRepository.Delete(playlist);
unitOfWork.Commit();

return PlaylistDTO(playlist);
}

此代码失败。当我通过调试器时,我注意到一些有趣的事情。我调用 playlistRepository.Delete 的那一刻,导航属性(用户和轨道)分别设置为 null 和空。然而,播放列表保留在内存中。因此,当我将播放列表传递给 DTO 时,代码将在尝试访问 playlist.User.Name 时失败。我想将此数据传递给客户端以显示验证。

这种行为是否正确?这是故意的吗?

最佳答案

这就是EF的工作方式。问题是你的 Playlist与其他关系形成实体图,EF 使用非常简单的规则来跟踪实体图:必须跟踪图中的所有实体 - 不能引用未跟踪的实体。我没有给你引用这条规则的描述,这只是我的观察,但我没有发现这条规则有任何异常(exception)。

编辑:更新版本 - 我刚刚检查了内部实现,并且在调用 Delete 期间关系确实无效

那么你的代码中发生了什么。

  • 您标记了您的 Playlist如已删除
  • EF 将删除操作传递给进行修复的状态管理器 - 它将使所有关系无效
  • 您保存了对数据库的更改
  • 因为没有来自 Playlist 的级联删除所有相关对象保持未删除
  • 保存更改后,EF 内部接受它们并将更改跟踪器设置为当前状态
  • 因为Playlist的当前状态不存在(已在数据库中删除)它已从上下文中分离
  • 分离破坏了实体图,EF 通过修改两端的导航属性修复了它

  • 负责归零的代码来自 System.Data.Objects.EntityEntry.Delete(doFixup) ( doFixup 为真) - 类是内部的:
    if (doFixup && (base.State != EntityState.Deleted))
    {
    this.RelationshipManager.NullAllFKsInDependentsForWhichThisIsThePrincipal();
    this.NullAllForeignKeys();
    this.FixupRelationships();
    }

    在您的场景中,这应该有简单的解决方法 - 在删除实体之前创建 DTO。

    关于entity-framework-4.1 - 在 EF 代码中删除首先会导致导航属性设置为 null 和空,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6778431/

    24 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com