Nhibernate 复合Id';s和Restrictions.IdEq或与Linq中的比较不按预期工作
我有一个使用复合id的实体。我改为使用代码将复合id包装在一个单独的键类中。我希望使用Linq可以对key对象和Criteria API进行比较,以使用Restrictions.IdEq,但两者都失败了。我需要显式地比较键值以使其工作 我找不到任何文件,如果这应该工作,所以目前我只能进行直接比较,但这意味着,当我更改密钥时,我还需要更新查询代码,这显然不是我想要的 作为旁注,我用NHibernate 3.0.0 Alpha 2和3尝试了这个 领域 映射 工作查询 下面的查询有效,正如您所看到的,我显式地比较了键值。我不比较关键对象 林克 林克Nhibernate 复合Id';s和Restrictions.IdEq或与Linq中的比较不按预期工作,nhibernate,criteria,linq-to-nhibernate,nhibernate-criteria,Nhibernate,Criteria,Linq To Nhibernate,Nhibernate Criteria,我有一个使用复合id的实体。我改为使用代码将复合id包装在一个单独的键类中。我希望使用Linq可以对key对象和Criteria API进行比较,以使用Restrictions.IdEq,但两者都失败了。我需要显式地比较键值以使其工作 我找不到任何文件,如果这应该工作,所以目前我只能进行直接比较,但这意味着,当我更改密钥时,我还需要更新查询代码,这显然不是我想要的 作为旁注,我用NHibernate 3.0.0 Alpha 2和3尝试了这个 领域 映射 工作查询 下面的查询有效,正如您所看到的,
来自状态
在session.Query()中
其中status.Id==key
选择状态
标准API
session.CreateCriteria()
.添加(限制。IdEq(关键))
那么,如果有人有这样的场景,那么我做错了什么呢?有趣的是,我在2.1.2中得到了与此行为几乎完全相反的结果 我的映射(简化): 有效的东西:
CreateCriteria()
.Add(Restrictions.IdEq(keyInstance))
.UniqueResult();
CreateCriteria()
.Add(Restrictions.Eq(“SubscriberKey.User.Id”,aUserID))
.Add(Restrictions.Eq(“SubscriberKey.Request”,aRequestID))
.UniqueResult();
不起作用的事情:
Get(keyInstance);
我认为这是他们各种ID相等查询表单之间的不一致。当我有时间的时候,我将构建一个最小的单元测试作为bug示例提交。我对任何人对这件事的想法都感兴趣
编辑:嘿,我知道了 我已经读过了,那些有用的东西
Get(新SubscriberKey(){
User=Load(aUserID),//重要部分!
请求=aRequestID
});
这将为用户密钥创建一个代理对象,而不会命中数据库(除非必要)。如果您将Load
交换为Get
,您将立即点击数据库来填充对象,而不考虑延迟加载属性。使用负载
这正是人们建议使用(类型)存储库模式的原因——我可以在幕后这样做:
Get(new SK(){User=Load(key.User.Id)}
,并且仍然Get(key)
通过一个键,与所有其他对象相同。不是对您的问题的直接回答,但它可能对您很有用。您可以通过将AddonStatus映射为所有者(很可能是上下文)上的复合元素来避免(显式)复合键:
这个结果和数据库结构基本相同,但使用起来不同。我不能说这是否是您真正想要的,但它看起来就是这样。我知道这个结构并经常使用它。但是,is与查询复合id无关。这个结构的另一个问题是当您想要查询at返回所有AddonStatus值,其中其父上下文的属性具有特定值,因此是上下文和AddonStatus之间的连接。其次,我没有得到的是带有Restriction.IdEq(..)的criteria api查询很好用!你能指定你是如何在Subscriber和SubscriberKey上实现Equals/GetHashCode方法的吗?也许beta版和GA版之间发生了一些变化。我将很快对此进行测试以验证。第三,我知道Load/Get行为,不使用criteria api通过主键检索对象。我简化了e scenerio,直到剩下的都是这个,但实际的查询会导致几个内部联接。@Ramon:更新了代码示例以显示eq/ghc。实际上,只有SubscriberKey需要它们,因为它是复合id。可能我误用了这些,我对NHibernate比较陌生,但到目前为止它一直在工作。现在我正在与悬挂做斗争单元测试中的会话。。。
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
assembly="Cwc.Pulse.Dal"
namespace="Cwc.Pulse.Dal">
<class name="AddonStatus">
<composite-id name="Id">
<key-many-to-one name="Context" column="Context_Id" class="Context" />
<key-property name="AddonType" column="Addon_Id"/>
</composite-id>
<property name="Status" />
</class>
</hibernate-mapping>
public class AddonStatus
{
public virtual string Status { get; set; }
public virtual Key Id { get; protected set; }
public AddonStatus()
{
Id = new Key();
}
public class Key
{
public virtual Context Context { get; set; }
public virtual AddonType AddonType { get; set; }
public override int GetHashCode()
{
return ContextId.GetHashCode() ^ AddonType.GetHashCode();
}
public override bool Equals(object obj)
{
if (this == obj) return true;
var o = obj as Key;
if (null == o) return false;
return Context == o.Context && AddonType == o.AddonType;
}
}
}
from status
in session.Query<AddonStatus>()
where status.Id.Context == context && status.Id.AddonType == addonType
select status
session.CreateCriteria<AddonStatus>()
.Add(Restrictions.Eq("Id.Context", context))
.Add(Restrictions.Eq("Id.AddonType", addonType))
var key = new AddonStatus.Key
{
Context = context,
AddonType = addonType
};
from status
in session.Query<AddonStatus>()
where status.Id == key
select status
session.CreateCriteria<AddonStatus>()
.Add(Restrictions.IdEq(key))
<!-- Subscriber class -->
<class name="Subscriber" >
<composite-id name="SubscriberKey" class="SubscriberKey">
<key-property name="Request" column="RequestID" type="int"/>
<key-many-to-one name="User" column="UserID" class="User" not-found="ignore" />
</composite-id>
<!-- User class - note that this goes to a different schema,
and is not mutable. Who knows if that's important... -->
<class name="User" schema="AnotherDb.dbo" mutable="false">
<id name="Id" column="UserID" type="int">
<generator class="native" />
</id>
<property name="FirstName" column="FirstName" type="string" />
<property name="LastName" column="LastName" type="string" />
public class User
{
public virtual int? Id {get; protected set;}
public virtual string FirstName { get; protected set; }
public virtual string LastName { get; protected set; }
public User() { }
}
public class Subscriber
{
public virtual SubscriberKey SubscriberKey { get; set; }
public virtual User User { get; set; }
public Subscriber() { }
}
public class SubscriberKey
{
public override bool Equals(object obj)
{
if (obj is SubscriberKey && obj != null)
return ((SubscriberKey)obj).Request == Request
&& ((SubscriberKey)obj).User.Id == User.Id;
return false;
}
public override int GetHashCode()
{
return (Request.ToString() + User.Id.ToString()).GetHashCode();
}
public virtual int Request { get; set; }
public virtual User User { get; set; }
public SubscriberKey() { }
}
CreateCriteria<Subscriber>()
.Add(Restrictions.IdEq(keyInstance))
.UniqueResult<Subscriber>();
CreateCriteria<Subscriber>()
.Add(Restrictions.Eq("SubscriberKey.User.Id", aUserID))
.Add(Restrictions.Eq("SubscriberKey.Request", aRequestID))
.UniqueResult<Subscriber>();
Get<Subscriber>(keyInstance);
Get<Subscriber>(new SubscriberKey() {
User = Load<User>(aUserID), // the important part!
Request = aRequestID
});
<class name="Context">
<map name="AddonStates" table="AddonStatus">
<key column="Context_Id" /> <!-- Foreign key to the Context -->
<index column="Addon_Id" /> <!-- Dictionary key -->
<composite-element>
<property name="Status" /> <!-- data -->
</composite-element>
</map>
</class>
class Context
{
IDictionary<AddonType, AddonStatus> AddonStates { get; private set; }
}