Linq to NHibernate does not return proper data
I have a class
public class Item : IItem
{
public virtual Guid Id { get; set; }
public virtual string Name { get; set; }
public virtual bool IsActive { get; set; }
}
public interface IItem
{
Guid Id { get; set; }
string Name { get; set; }
bool IsActive { get; set; }
}开发者_开发百科
public class ItemMap : ClassMap<Item>
{
public ItemMap()
{
Id(x => x.Id);
Map(x => x.Name);
Map(x => x.IsActive);
}
}
In my database I have created five items. Three that have the IsActive flag set to true and two that have it set to false.
When using the Interface it returns all five items:
var q = from i in session.Linq<IItem>()
where i.IsActive == true
select i;
However, when using the concrete class it returns the proper three items:
var q = from i in session.Linq<Item>()
where i.IsActive == true
select i;
EDIT
I have would like to return an Interface, because I have read that I should return non-concrete classes. Please note that in actuality, these Linq queries are in a repository in a different project (in case this becomes a web or WPF app)It looks like a bug in the old contrib Linq provider.
Try with NHibernate 3, it works as expected.
I believe you will need to map IItem instead of the concrete Item class to have this work properly.
Things you could try:
Instead of
public class ItemMap : ClassMap<Item>
use
public class ItemMap : ClassMap<IItem>
Simply cast the objects that are returned:
var q = from i in session.Linq<Item>() where i.IsActive == true select (IItem)i;
I don't think you need to worry about querying against concrete types, that is fine. Just have your repository method return an interface. Make sense?
public IItem GetItem(int id)
{
var item = from i in session.Linq<Item>()
where i.IsActive == true
select i;
return item;
}
This will let you query work as it should and let all your dependent code work against the interface, which is all you really need the interface for anyway.
I've posted a similar issue here and ended up dropping hibernate (for unrelated reasons however). I don't think LINQ is really "finished" in hibernate yet, there are still some methods i.e. Enumerable() that throw a not implemented exception.
However, to answer your question I found that I HAD to use concrete classes and not interfaces because there is no *.hbm.xml file for the interface so hibernate doesn't know how to map the interface to its respective table. As someone said on my post, I am probably taking this loose coupling thing a little too far, as you should only use loose coupling and inversion of control in areas of potentially lots of change - but yeah database models do change a lot.
I think the key here is to make sure that your business domain is in its own assembly "MyBusiness.Domain" and have all projects reference this. All these projects will then have interfaces specified (design by contract) and the concrete classes and injected using something like Ninject, that way you can instantiate new classes in your business domain and as long as they implement the relevant interfaces your projects can use them.
As you can see I'm no expert at this... yet... but I think this way of developing software is basically doing it properly, and it's fairly complicated when starting out!
精彩评论