在我的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
事件处理程序中生成的密钥。
我在这里做错了什么?
答案 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'"
}));
});
.......
}
}
希望这会有助于其他人。我们非常感谢对此解决方案的改进。