Tho*_*mas 4 ef-code-first entity-framework-4.1
当我首先使用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; }
}
Run Code Online (Sandbox Code Playgroud)
该模型使用以下配置:
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"));
}
Run Code Online (Sandbox Code Playgroud)
我使用通用存储库:
public virtual void Delete(T entity)
{
Database.Set<T>().Remove(entity);
}
Run Code Online (Sandbox Code Playgroud)
我也有一个看起来像的dto:
public class PlaylistDTO
{
public PlaylistDTO(Playlist playlist)
{
Id = playlist.Id;
Title = playlist.Title;
User = playlist.User.Name;
}
}
Run Code Online (Sandbox Code Playgroud)
在我的一项服务中,我尝试执行以下操作:
public PlaylistDTO Delete(long id)
{
Playlist playlist = playlistRepository.GetById(id);
playlistRepository.Delete(playlist);
unitOfWork.Commit();
return PlaylistDTO(playlist);
}
Run Code Online (Sandbox Code Playgroud)
此代码失败.当我通过调试器时,我发现了一些有趣的东西.我调用playlistRepository.Delete时,导航属性(User和Tracks)分别设置为null和empty.然而,播放列表会留在内存中.因此,当我将播放列表传递给DTO时,代码将在尝试访问playlist.User.Name时失败.我想将此数据传递给客户端以显示验证.
这种行为是否正确?这是设计的吗?
这就是EF的工作原理.问题是您的Playlist表单实体图与其他关系和EF使用非常简单的规则来跟踪实体图:必须跟踪图中的所有实体 - 不能引用未跟踪的实体.我没有给你参考这条规则的描述,这只是我的观察,但我没有发现任何一个例外.
编辑:更新版本 - 我刚刚检查了内部实现,并且在调用Delete期间确实关系无关
那么代码中发生了什么.
Playlist为已删除Playlist所有相关对象的级联删除仍未删除Playlist不存在(在数据库中删除),因此它与上下文分离负责归零的代码System.Data.Objects.EntityEntry.Delete(doFixup)(doFixup是真的) - 该类是内部的:
if (doFixup && (base.State != EntityState.Deleted))
{
this.RelationshipManager.NullAllFKsInDependentsForWhichThisIsThePrincipal();
this.NullAllForeignKeys();
this.FixupRelationships();
}
Run Code Online (Sandbox Code Playgroud)
在您的方案中,这应该有简单的解决方法 - 在删除实体之前创建DTO.
| 归档时间: |
|
| 查看次数: |
826 次 |
| 最近记录: |