我有以下实体:
public class Entity1
{
public Guid ID { get; set; }
public override int GetHashCode()
{
return ID.GetHashCode();
}
}
public class Entity2
{
public Dictionary<Entity1,int> Dict { get; set; }
}
我重写Entity1的GetHashCode以反映它的ID,因为它是它具有的最不可变的属性,而不是通过引用保留它,因为我正在运行多个会话,并且字典必须是“会话”安全的。
在本次讨论中,我在字典中有一个int值,该值并不真正相关。
使用NHibernate可以正确映射两个实体。
可以说我有以下代码:
using (var session = GetSession())
{
var entity1 = new Entity1();
var entity2 = new Entity2();
entity2.Dict[entity1] = 1;
session.SaveOrUpdate(entity1);
session.SaveOrUpdate(entity2);
}
在此代码中,Dict不会保存任何键值-因为在保存之前将Entity1添加到Dict中时,它将为它提供一个空ID的哈希码,该哈希码紧随其后将以实际ID保存,从而破坏了字典。
我正在寻找最佳实践/最佳解决方案。
我目前的选择:
请记住,在将Entity1添加到任何词典(我有一堆)之前,请务必保存它。我不喜欢这个选项,因为它确实不是傻瓜式的,而且我相信以后其他人也不会注意这一点,并且会造成可怕的错误。
在保存之前-总是反复检查键,值集合,保存键并将它们重新分配到字典中,此解决方案似乎确实缺乏性能,并且会引起各种不同的问题。但最重要的是-听起来应该有一个更好的解决方案。
处理这种情况的最佳方法是什么?
在我的项目中,我们自己进行ID生成:
private int _id = -1;
public virtual Id
{
get {return _id == -1? (_id = IdGenerator.GenerateNextId()): _id;}
protected set {_id = value;}
}
IdGenerator是HiLo(TableHiLo或SequenceHiLo)的实现。然后使用assigned
ID生成策略映射所有实体:
<id name="Id" column="ID">
<generator class="assigned" />
</id>
按照这种安排,当访问Id属性时,所有对象都将具有唯一的ID,并且该ID永远不会更改。该解决方案已经为我服务了三年,而且没有任何复杂性。但是,转换现有系统可能很复杂。
阅读本文后,我想到了这一点:不要让休眠模式窃取您的身份
编辑:
有两个选项可以检测未保存的对象。一种是使用版本属性。但是,并非所有实体都需要这样的属性,因此我使用了一个拦截器来跟踪实体的瞬时状态:
public interface ITransienceAware
{
bool IsTransient {get; set;}
}
所有实体的基类都显式实现此接口(从视图中隐藏IsTransient属性,避免愚蠢的错误,因为需要将对象强制转换为ITransienceAware来更改值):
public abstract class MappedEntity: ITransienceAware // and some more unrelated interface
{
//...................unrelated code
bool ITransienceAware.IsTransient { get; set; }
//...................unrelated code
}
拦截器OnLoad和OnSave方法将IsTransient更改为true。
另一个重要的实现细节是IdGenerator:它是用于SQL Server的TableHiLo和用于Oracle的SequenceHiLo的实现,并且它必须在单独的事务中访问数据库以防止跨请求锁定。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句