我们有一个旧的,具有nhibernate的大型asp.net应用程序,我们正在扩展和升级它的某些部分。使用的NHibernate很旧(1.0.2.0),所以我们决定升级到(2.1.2)以获得新功能。 HBM文件是通过MyGeneration的自定义模板生成的。除了一件事,一切都很顺利。
让我们说我们必须对象Blog和Post。博客可以有很多帖子,所以Post会有多对一的关系。由于此应用程序的运行方式,关系不是通过主键,而是通过Blog.Reference列完成的。
示例映射和.cs文件:
<?xml version="1.0" encoding="utf-8" ?>
<id name="Id" column="Id" type="Guid">
<generator class="assigned"/>
</id>
<property column="Reference" type="Int32" name="Reference" not-null="true" />
<property column="Name" type="String" name="Name" length="250" />
</class>
<?xml version="1.0" encoding="utf-8" ?>
<id name="Id" column="Id" type="Guid">
<generator class="assigned"/>
</id>
<property column="Reference" type="Int32" name="Reference" not-null="true" />
<property column="Name" type="String" name="Name" length="250" />
<many-to-one name="Blog" column="BlogId" class="SampleNamespace.BlogEntity,SampleNamespace" property-ref="Reference" />
</class>
和班级文件
class BlogEntity
{
public Guid Id { get; set; }
public int Reference { get; set; }
public string Name { get; set; }
}
class PostEntity
{
public Guid Id { get; set; }
public int Reference { get; set; }
public string Name { get; set; }
public BlogEntity Blog { get; set; }
}
现在让我说我的博客ID为1D270C7B-090D-47E2-8CC5-A3D145838D9C,参考文献1
在旧的nhibernate这样的事情是可能的:
//this Blog already exists in database
BlogEntity blog = new BlogEntity();
blog.Id = Guid.Empty;
blog.Reference = 1; //Reference is unique, so we can distinguish Blog by this field
blog.Name = "My blog";
//this is new Post, that we are trying to insert
PostEntity post = new PostEntity();
post.Id = Guid.NewGuid();
post.Name = "New post";
post.Reference = 1234;
post.Blog = blog;
session.Save(post);
但是,在新版本中,我得到一个异常,无法在Post.BlogId中插入NULL。据我所知,在旧版本中,对于nhibernate,它足以拥有Blog.Reference字段,它可以通过该字段检索实体,并将其附加到PostEntity,并且在保存PostEntity时,一切都能正常工作。据我了解,新的NHibernate只尝试通过Blog.Id检索。
如何解决这个问题?我无法更改数据库设计,也无法为BlogEntity分配ID,因为对象不受我的控制(它们预先填充为来自外部源的通用“ojbects”)
答案 0 :(得分:0)
我觉得这个代码在NH 1中工作似乎很奇怪。但是,由于它现在无法正常工作,我认为你必须首先在查询中寻找博客实体:
var criteria = DetachedCriteria.For<Blog>();
criteria.Add(Expression.Eq("Reference", 1));
var blog = criteria.GetExecutableCriteria(session).List<Blog>().FirstOrDefault();
post.Blog = blog;
session.Save(post);
答案 1 :(得分:0)
此
blog.Id = Guid.Empty
在DB中被翻译为null。因此,当您更改它时(如示例代码所示),您将在BlogEntity Id上明确设置空值。
这是您收到的错误,与“参考”栏/属性无关。
至于你能做什么的问题......你不必在Guids上加入ORM!您可以在参考列上进行连接...
答案 2 :(得分:0)
回答我自己的问题。
问题是nhibernate正在等待DB检索具有标识00000000-0000-0000-0000-000000000000的BlogEntity。当然在DB中它什么都没有,所以它试图插入null
在日志中可以清楚地看到它发生的原因
无法确定BlogEntity是否与 分配标识符 00000000-0000-0000-0000-000000000000 是暂时的或分离的;查询 数据库。使用显式Save()或 在会话中更新()以防止这种情况。
解决了我的实施IInterceptor
,将其传递给Session,特别是其方法bool? IsTransient(object entity)
问题解决了。