NHibernate:在OnPreInsert中生成自定义主键

时间:2014-08-01 12:27:54

标签: c# nhibernate

在我的OData服务中,我必须在OnPreInsert事件处理程序中创建一个自定义主键。

我知道我不能使用@event.Id来分配密钥,因为它没有公开setter属性。

我使用反射来设置此属性的值,如下所示:

public bool OnPreInsert(PreInsertEvent @event)
{

    if(@event.Entity is MyEnity)
    {            
        var myEntity = @event.Entity as MyEnity;


        string newKey = GetCustomKey(...);

            myEntity.myId = newKey;                
            var property = typeof(AbstractPreDatabaseOperationEvent).GetProperty("Id");
            if (property != null)
            {
                property.SetValue(@event,newKey);
            }
        }

        return false;
}

在调试模式期间,我可以看到@event.Id的值已正确初始化,但保存在数据库中的密钥不是我在OnPreInsert事件处理程序中生成的密钥。

我在这里做错了什么?

2 个答案:

答案 0 :(得分:0)

请尝试查看最近的Q& A:

关键是,如下所述:

  

......然而,这是微妙的。我们不能只更新实体状态。原因很简单,实体状态是从实体中提取出来并放置在实体状态中,我们对实体状态所做的任何更改都不会反映在实体本身中。这可能是导致数据库行和实体实例不同步,并导致一大堆非常讨厌的问题,你不知道从哪里开始调试。

     

您必须在这两个事件侦听器中同时更新实体和实体状态(顺便说一下,在其他侦听器中不一定如此)。以下是使用这些事件侦听器的简单示例...

答案 1 :(得分:0)

我找不到某种方法来使用反射来实现我在上面的问题中描述的内容。我尝试使用反射,因为我不知道NHibernate中可用的Generators(因为我是NHibernate的新手)。

我有一个名为 sys_params 的表,它保存不同表的下一个键值。我的目标是获取表 my_entity 的下一个键,将其分配给新记录的主键,递增 sys_params 表中的下一个键值并保存新记录到数据库中。

为了实现这一点,我首先定义了以下类。

public class NextIdGenerator : TableGenerator
{
}

public class NextIdGeneratorDef : IGeneratorDef
{
    public string Class
    {
        get { return typeof(NextIdGenerator).AssemblyQualifiedName; }
    }

    public object Params
    {
        get { return null; }
    }

    public Type DefaultReturnType
    {
        get { return typeof(int); }
    }

    public bool SupportedAsCollectionElementId
    {
        get { return true; }
    }
}

然后在我的映射类中,我定义了如下的生成器:

public class MyEnityMap : ClassMapping<MyEnity>
{
    public MyEnityMap()
    {
        Table("my_entity");
        Id(p => p.myId,
           m=>{
               m.Column("my_id");
               m.Generator(new NextIdGeneratorDef(), g =>g.Params( new
               {
                   table = "sys_params",
                   column = "param_nextvalue",
                   where = "table_name = 'my_entity'"
               }));
           });

        .......                   
    }
}

希望这会有助于其他人。我们非常感谢对此解决方案的改进。