【问题标题】:NHibernate issue with assigned string ID and different case chars分配字符串 ID 和不同大小写字符的 NHibernate 问题
【发布时间】:2016-01-11 05:10:37
【问题描述】:

在 NHibernate 上保存具有分配字符串 Id 的实体时遇到问题...我尝试用一​​个示例来解释这个问题。

如果我执行这些语句,假设数据库中有一个 ID 为“AAA”的实体

ENTITYTYPE entity = Session.Get<ENTITYTYPE>("AAA");
ENTITYTYPE newentity = new ENTITYTYPE() { Id = "aaa" };

Session.Delete(entity);
Session.Save(newentity);
Session.Flush();

在 Flush NHibernate 上引发异常并显示以下消息:“无法将数据库状态与会话同步”/“违反主键”

大小写敏感 ID 似乎有问题,如果我在“newentity”的 ID 上使用“AAA”,那么它可以工作,但在我的情况下并不那么容易,我必须找到一个替代解决方案。

如何避免这个异常?你能帮帮我吗?

【问题讨论】:

  • 您使用的是哪个数据库?
  • 为什么会有字符串标识符?
  • "为什么你有字符串标识符?"...遗留数据库:(

标签: c# nhibernate session save identity


【解决方案1】:

我不知道它是否足够,但你可以用这样的东西来控制它:

public override bool Equals(object obj)
{
T other = obj as T;
if (other == null)
    return false;

// handle the case of comparing two NEW objects
bool otherIsTransient = Equals(other.Id, Guid.Empty);
bool thisIsTransient = Equals(Id, Guid.Empty);
if (otherIsTransient && thisIsTransient)
    return ReferenceEquals(other, this);

return other.Id.ToUpper().Equals(Id.ToUpper());
}

在比较实体时使用 ToUpper() 或 ToLower() 方法,或者您可以使用 String.Compare(stringA,strngB,StringComparison.OrdinalIgnoreCase)。

如果您想要更多控制权并且这是您的目标,您可以创建自定义 ID 生成器,如下所述:

http://nhibernate.info/doc/howto/various/creating-a-custom-id-generator-for-nhibernate.html

更新

您是否尝试过创建自定义 GetIgnoreCase(...)?

我认为也可以通过加载器标记覆盖实体映射文件中默认 Get 方法生成的 SELECT 语句,如下例所示:

       ...
      <loader query-ref="loadProducts"/>
 </class>

 <sql-query name="loadProducts">
 <return alias="prod" class="Product" />
 <![CDATA[
  select 
    ProductID as {prod.ProductID}, 
    UnitPrice as {prod.UnitPrice}, 
    ProductName as {pod.ProductName}
  from Products prod
  order by ProductID desc
]]>

您可以尝试修改返回大写 ID 的 select 语句。

更新

经过进一步调查,我认为使用拦截器可以解决您的问题!

在这里阅读:

http://knol.google.com/k/fabio-maulo/nhibernate-chapter-11-interceptors-and/1nr4enxv3dpeq/14#

更多文档在这里:

http://blog.scooletz.com/2011/02/22/nhibernate-interceptor-magic-tricks-pt-5/

类似这样的:

 public class TestInterceptor
  : EmptyInterceptor, IInterceptor
{
    private readonly IInterceptor innerInterceptor;

    public TestInterceptor(IInterceptor innerInterceptor)
    {
        this.innerInterceptor = this.innerInterceptor ?? new EmptyInterceptor();
    }

    public override object GetEntity(string entityName, object id)
    {
        if (id is string)
            id = id.ToString().ToUpper();

        return this.innerInterceptor.GetEntity(entityName, id);

    }

}

并像这样流利地注册它:

return Fluently.Configure()
           ...
            .ExposeConfiguration(c =>{c.Interceptor = new TestInterceptor(c.Interceptor ?? new EmptyInterceptor());})
            ...
            .BuildConfiguration();

【讨论】:

  • mmm...我尝试修改我的 Equals 实现但不起作用,当我运行上面的代码时,永远不会调用 Equals 方法...可能吗?我还要修改 GetHashCode 方法?
  • 好的,但我正在寻找一种适用于我的项目的每个实体的解决方案,这些实体具有分配的字符串 Id...有什么想法吗?
  • 目前尚不清楚人们投票支持哪些解决方案,您可能应该将它们分成单独的答案。
猜你喜欢
  • 2014-09-07
  • 2019-11-22
  • 2022-06-12
  • 2013-05-03
  • 2023-03-10
  • 2022-11-14
  • 2014-10-26
  • 2017-12-09
  • 2018-04-28
相关资源
最近更新 更多