Reputation: 8166
I am using nHibernate and am trying to populate an entity, which has a subclass of another entity from a stored procedure. I have a RankedListing which contains an Id, a Rank and a Listing
public class RankedListing : DomainEntity
{
public virtual int Id { get; set; }
public virtual int Rank { get; set; }
public virtual Listing Listing { get; set; }
}
I am calling a stored procedure to populate this entity from a FULLTEXT
search. The stored procedure returns three columns (Id, Rank, and Listing_Id). The code that I'm executing is below.
IQuery query = ServiceLocator.Current.GetInstance<INHibernateUnitOfWork>().CurrentSession.CreateSQLQuery("exec dbo.usp_SearchListings :Search");
query.SetString("Search", search);
var products = query.SetResultTransformer(Transformers.AliasToBean(typeof(RankedListing))).List<RankedListing>().ToList();
return products;
When I execute this, the error that I get back is:
Could not find a setter for property 'Listing_Id' in class 'RankedListing'
Is there anyway to get this to map the Listing on the RankedListing rather than trying to map it as the column name as a property.
Upvotes: 0
Views: 1196
Reputation: 30813
i dont know if it's the best way but a custom resulttransformer could do
class MyTransformer : IResultTransformer
{
private ISession _session;
private Dictionary<int, int> _listingIds = new Dictionary<int, int>();
public MyTransformer(ISession session)
{
_session = session;
}
public IList TransformList(IList collection)
{
var listings = _session.QueryOver<Listing>()
.WhereRestrictionOn(l => l.Id).IsIn(_listingIds.Values)
.List().ToDictionary(l => l.Id);
return collection.Cast<RankedListing>()
.Select(rl => { rl.Listing = listings[_listingIds[rl.Id]]; return rl; })
.ToList();
}
public object TransformTuple(object[] tuple, string[] aliases)
{
var rl = new RankedListing();
rl.Id = (int)tuple[System.Array.FindIndex(aliases, name => name == "Id")];
rl.Rank = (int)tuple[System.Array.FindIndex(aliases, name => name == "Rank")];
_listingIds.Add(rl.Id, (int)tuple[System.Array.FindIndex(aliases, name => name == "Listing_Id")]);
return rl;
}
}
then use it like:
var products = query.SetResultTransformer(new MyTransformer(CurrentSession)).List<RankedListing>();
Update: if you want to lazyload the Listings you could also do
.Select(rl => { rl.Listing = session.Load<Listing>(_listingIds[rl.Id]); return rl; })
Upvotes: 2