开发者

nHibernate query exception: no row with given identifier exists

开发者 https://www.devze.com 2023-04-10 22:56 出处:网络
After modifying the datamodel a little bit, certain queries started giving me this exception. However, even after reading various forum-threads and blogs, I don\'t understand why this happens in my ca

After modifying the datamodel a little bit, certain queries started giving me this exception. However, even after reading various forum-threads and blogs, I don't understand why this happens in my case. So I hope that someone here can help. First, an example query:

var criteria = Session.CreateCriteria(typeof(SomeEntity));
        criteria.Add(Expression.IdEq(id));
        criteria.SetFetchMode("_PrivateProperty", FetchMode.Eager);
        criteria.CreateAlias("PublicProperty", "alias");
        criteria.Add(Expression.Eq("alias.Id", aliasId));

If I modify the query by either removing (1) SetFetchMode or (2) CreateAlias for the public property, everything works fine.

The private property is usually loaded lazily, but in this case I want to load it together with its parent entity to combat select N+1.

So, why doesn't it work as displayed above, and does it work when I remove certain parts of the query?

UPDATE

Generated SQL:

SELECT * FROM SomeEntity this_ 
inner join PublicProperty alias4_ on this_.SomeEntityId=alias4_开发者_StackOverflow中文版.SomeEntityId 
inner join ReferencedProperty rp2_ on alias4_.RPId=rp2_.RPId 
left outer join PrivateProperty v1_ on this_.SomeEntityId=v1_.SomeEntityId 
WHERE this_.SomeEntityId= @p0 and rp2_.RPId= @p1

When run in SQL Server Management Studio, it works as expected. I get two results. In between modifying the datamodel and the query, the data in the database hasn't changed.

UPDATE2

Modification in model. Original mapping:

References(d => d.PublicProperty, "PublicPropertyId").Cascade.SaveUpdate();

New mapping:

HasManyToMany(d => d.PublicPropertys)
            .Access.CamelCaseField(Prefix.Underscore)
            .Table("SomeEntityPublicProperty")
            .ParentKeyColumn("SomeEntityId")
            .ChildKeyColumn("PublicPropertyId")
            .Cascade.SaveUpdate()
            .Inverse();

UPDATE3

HasMany<PrivatePropertyEntity>(Reveal.Member<SomeEntity>("_PrivateProperty"))
            .Table("SomeEntity_PrivateProperty")
            .KeyColumn("SomeEntityId")
            .Cascade.AllDeleteOrphan()
            .LazyLoad().Inverse();


Your problem likely stems from the fact that if you use createalias (without specifying an outer join type) the entities don't get loaded eagerly in spite of what your configuration is.

The reason for this related to your error: Assuming you didn't specify any criteria on the RHS of the association, and you have null references in your data, using an INNER JOIN would incorrectly filter out records on the LHS.

As such, it doesn't matter to NHibernate that your query returns two results using the INNER JOINS it goes ahead and lazy loads the associations anyway. Somewhere you have a reference to a non-existent referenced property in your many-to-many join table, and it is failing when it tries to lazy load it to check whether the RHS matches you criteria.

Changing the alias to perform a left outer join should prevent the error (it will actually load the associated entities eagerly and not re-check the references), but you'll still have that referential integrity problem somewhere:

criteria.CreateAlias("PublicProperty", "alias", JoinType.LeftOuterJoin);
0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号