【发布时间】:2019-08-12 15:54:20
【问题描述】:
我有一些实体(为简单起见,看起来像这样):
class DbEntity
{
public Guid Id {get;set;}
}
class BaseEntity: DbEntity
{
public string Name {get;set;}
public ParentEntity Parent {get;set;}
}
class ParentEntity: BaseEntity
{
List<BaseEntity> Children {get;set;}
}
class ChildEntity: BaseEntity
{
}
现在,我的流畅映射看起来像这样:
class DbEntityMap<T>: ClassMap<T> where T: DbEntity
{
public DbEntityMap()
{
Id(x => x.Id).GeneratedBy.GuidComb();
}
}
class BaseEntityMap: DbEntityMap<BaseEntity>
{
UseUnionSubclassForInheritanceMapping();
Map(x => x.Name).Not.Nullable();
References(x => x.Parent).Cascade.None();
}
class ParentEntityMap: SubclassMap<ParentEntity>
{
Abstract();
HasMany(x => x.Children)
.ForeignKeyCascadeOnDelete()
.Inverse()
.Not.KeyUpdate()
.Cascade.None()
.LazyLoad();
}
class ChildEntityMap: SubclassMap<ChildEntity>
{
Abstract();
//some other stuff
}
现在,我有向 WebAPI 发送请求的客户端桌面应用程序。 第一个请求是创建所有实体,例如:
ParentEntity parent = new ParentEntity();
parent.Name = "New name";
ChildEntity child1 = new ChildEntity();
ChildEntity child2 = new ChildEntity();
parent.Children.Add(child1);
parent.Children.Add(child2);
//of course children know their parent:
//child.Parent = parent;
现在我正在构建一些 dto(因为我的模型要复杂得多,创建一个 dto 是个好主意)来构建一个 json,并将这个 json 发送到 WebAPI。数据库中的实体已正确创建。太好了。
但现在我要修改一些子实体,例如:
child1.SomeValue = newValue;
现在,在创建 DTO 时,我没有向其中添加父实体,只是父 id,它看起来更像这样:
class ChildDto
{
public Guid DbId {get;set;}
public Guid ParentDbId {get;set;}
public int SomeValue {get;set;}
}
现在,当我的 WebAPI 收到这样的 dto 时,它会重新创建这样的模型:
ParentEntity fakeParent = new ParentEntity();
fakeParent.Id = childDto.ParentDbId;
ChildEntity child = new ChildEntity();
//assign other child values and then parent:
child.Parent = fakeParent;
现在,当我执行 Update(just session.Update(obj, id)) 时,我的子实体会正确更新,但父实体也会更新。由于我没有在父实体中设置 Name 属性,所以数据库中的 Name 字段为空。
我认为将 Cascade 设置为 None 会阻止 NHibernate 更新父实体。但是没有级联设置有效。如果我将父绑定设置为:
References(x => x.Parent).ReadOnly()
然后我的 ChildEntity 会在没有父 ID 的情况下更新。
我至少知道几个解决方案,例如: 1. 在 DTO 中转换整个父实体 - 但这可以进行其他级联更新,如果没有 - 将有两个更新而不是一个。 2. 在更新之前选择父实体 - 但这会创建不必要的 SELECT。
我想要实现的是: - 仅更新 childEntity - 不更新父实体或任何其他实体。
我怎样才能做到这一点?
[关于实际应用的一些话]
实际上,我的 ParentEntity 可以持有 BaseEntities。 ParentEntity 和 ChildEntity 也有一些共同的属性。
此外,ChildEntity 可以容纳其他 DbEntities。 子实体的子实体也持有其他 DbEntities,如下所示:
父实体->子实体->实体A->实体B->实体C (像一棵树)
(每个都派生自 DbEntity)。 我什至设法使用 session.Merge 解决了这个问题,但是当我尝试更新例如 EntityA 时,问题是一样的 - ChildEntity 失去与 ParentEntity 的连接:|
【问题讨论】:
标签: c# nhibernate