Here is what I do:
1. Define entities (some code skipped for clarity):
[DataServiceKey("CategoryID")]
public class Categories
{
public virtual int CategoryID { get; set; }
public virtual ICollection<Products> Products { get; set; }
/**/
}
public class CategoriesMap : ClassMap<Categories>
{
public CategoriesMap()
{
Id(x => x.CategoryID).GeneratedBy.Increment();
HasMany(x => x.Products)
.Table("Products")
.KeyColumn("CategoryID");
/**/
}
}
[DataServiceKey("ProductID")]
public class Products
{
public virtual int ProductID { get; set; }
public virtual int CategoryID { get; set; }
public virtual Categories Category { get; set; }
/**/
}
public class ProductsMap : ClassMap<Products>
{
public ProductsMap()
{
Id(x => x.ProductID);
Map(x => x.CategoryID);
References(x => x.Category).Not.LazyLoad()
.Column("CategoryID");
/**/
}
}
2. Define context
public class NorthwindContext : NHibernateDataContext
{
public NorthwindContext(ISession session) : base(session) { }
public IQueryable<Categories> Categories
{
get { return new
NhQueryable<Categories>(base.Session.As<ISessionImplementor>());
}
}
public IQueryable<Products> Products
{
get { return new
NhQueryable<Products>(base.Session.As<ISessionImplementor>());
}
}
/**/
public static ISessionFactory CreateSessionFactory(string
connectionString)
{
return Fluently.Configure()
.Database(MsSqlConfiguration.MsSql2008
.ConnectionString(connectionString)
.Cache(c => c
.UseQueryCache()
.ProviderClass<HashtableCacheProvider>())
.ShowSql())
.Mappings(m =>
m.FluentMappings.AddFromAssemblyOf<NorthwindContext>())
.BuildSessionFactory();
}
}
So far so good. All tests work.
3. Now I implement an OData service:
[ServiceBehavior(IncludeExceptionDetailInFaults = true)]
public class NHibernateMsSql : DataService<NorthwindContext>,
IDisposable
{
private ISession session;
public void Dispose()
{
if (this.session != null)
{
this.session.Dispose();
this.session = null;
}
}
public static void InitializeService(DataServiceConfiguration
config)
{
config.SetEntitySetAccessRule("*", EntitySetRights.All);
config.SetServiceOperationAccessRule("*",
ServiceOperationRights.All);
config.DataServiceBehavior.AcceptCountRequests = true;
config.DataServiceBehavior.AcceptProjectionRequests = true;
config.DataServiceBehavior.MaxProtocolVersion =
DataServiceProtocolVersion.V2;
config.UseVerboseErrors = true;
}
protected override void HandleException(HandleExceptionArgs args)
{
base.HandleException(args);
Elmah.ErrorLog.GetDefault(null).Log(new Error(args.Exception));
}
protected override NorthwindContext CreateDataSource()
{
var factory = NorthwindContext.CreateSessionFactory(
ConfigurationManager.ConnectionStrings["NorthwindContext.NH.MsSql"].ConnectionString);
this.session = factory.OpenSession();
this.session.FlushMode = FlushMode.Auto;
return new NorthwindContext(this.session);
}
Then it works fine for non-projection queries but fails as soon as I call
SelectMany on it.
Vagif
On Tue, May 10, 2011 at 10:43 AM, Ricardo Peres <[email protected]> wrote:
> How are you creating the session/context? Are you using the
> DataService<T>.CreateDataSource() method?
>
>
> On May 9, 10:44 pm, Vagif Abilov <[email protected]> wrote:
> > ... and if I execute the same query
> >
> > context.Categories.Where(x => x.CategoryID == 1).SelectMany(x =>
> x.Products)
> >
> > using NH directly (not via OData service), it works fine. The error
> happens
> > only if send the query through WCF Data Service, and only if I use
> > NHibernate. With EF this is not a problem.
> >
> > Vagif
> >
> > On Mon, May 9, 2011 at 11:31 PM, Vagif Abilov <[email protected]
> >wrote:
> >
> >
> >
> >
> >
> >
> >
> > > Hi Ricardo,
> >
> > > Projection is enabled in my service and if I use Entity Framework
> instead
> > > of NH, the following query works fine:
> >
> > > Categories.Where(x => x.CategoryID == 1).SelectMany(x => x.Products)
> >
> > > But NH returns me the following error:
> >
> > > <message>element.Products is not mapped
> > >
> [.SelectMany[Northwind.NHibernate.MsSql.Categories,Northwind.NHibernate.MsS
> ql.Products](.Where[Northwind.NHibernate.MsSql.Categories](NHibernate.Linq.
> NhQueryable`1[Northwind.NHibernate.MsSql.Categories],
> > > Quote((element, ) => (Equal(element.CategoryID, p1))), ),
> Quote((element,
> > > ) => (Convert(element.Products))), )]</message>
> > > <type>NHibernate.Hql.Ast.ANTLR.QuerySyntaxException</type>
> >
> > > What I can do is to issue other query that works:
> > > Categories.Expand("Products").Where(x => x.CategoryID == 1)
> >
> > > But this one does not project Products, it just includes them in the
> result
> > > set. So I wonder if DataService needs more tweaking for NHibernate to
> > > correctly handle projection.
> >
> > > Vagif
> >
> > > On Mon, May 9, 2011 at 6:07 PM, Ricardo Peres <[email protected]>
> wrote:
> >
> > >> WCF Data Services supports projections (server-side, not client-side,
> > >> this you can always do with LINQ to Objects), but you have to enable
> > >> them:
> >
> > >> public static void InitializeService(DataServiceConfiguration config)
> > >> {
> > >> config.DataServiceBehavior.MaxProtocolVersion =
> > >> DataServiceProtocolVersion.V2;
> > >> config.DataServiceBehavior.AcceptProjectionRequests = true;
> > >> ...
> > >> }
> >
> > >> Also, I wrote a post on WCF Data Services debugging, a long time ago:
> >
> > >>http://weblogs.asp.net/ricardoperes/archive/2009/11/01/debugging-ado-.
> ..
> >
> > >> RP
> >
> > >> On May 9, 2:47 pm, Vagif Abilov <[email protected]> wrote:
> > >> > Hi,
> >
> > >> > After resolving my issue with navigation to referenced entities
> (thanks
> > >> > Ricardo), I am now testing possibility to fetch in OData only
> referenced
> > >> > entities. The following query fetches main entity and it's Products
> > >> > relation:
> > >> > Categories.Expand("Products").Where(c => c.CategoryID == 1)
> > >> > (corresponds
> > >>
> tohttp://localhost:50555/NorthwindEntityFrameworkModelFirstMsSql.svc/Ca...
> > >> > )
> >
> > >> > This is not what I want: I only need Products. I don't want to do
> > >> projection
> > >> > on the client.
> >
> > >> > When using Entity Framework, I can use the following (weird) C#
> syntax
> > >> in
> > >> > client code:
> > >> > from c in Categories.Where(c => c.CategoryID == 1) select new {
> Products
> > >> =
> > >> > c.Products }
> >
> > >> > But this does not work in NHibernate! I am getting NotImplemented
> > >> exception:
> >
> > >> > <message xml:lang="nb-NO">Not Implemented</message>
> > >> > <innererror>
> > >> > <message>([100001] As Categories)</message>
> > >> > <type>System.NotSupportedException</type>
> > >> > ...
> > >> > </message>
> >
> > >> > And using Expand("Products") does not seem to support projections:
> > >> > Categories.Expand("Products").Where(c => c.CategoryID == 1).Select(x
> =>
> > >> > x.Products) results in "The method 'Select' is not supported." both
> for
> > >> > NHibernate and Entity Framework.
> >
> > >> > Do you know about any workaround for this that will work in
> NHibernate?
> >
> > >> > Thanks in advance
> >
> > >> > Vagif
> >
> > >> --
> > >> You received this message because you are subscribed to the Google
> Groups
> > >> "nhusers" group.
> > >> To post to this group, send email to [email protected].
> > >> To unsubscribe from this group, send email to
> > >> [email protected].
> > >> For more options, visit this group at
> > >>http://groups.google.com/group/nhusers?hl=en.
>
> --
> You received this message because you are subscribed to the Google Groups
> "nhusers" group.
> To post to this group, send email to [email protected].
> To unsubscribe from this group, send email to
> [email protected].
> For more options, visit this group at
> http://groups.google.com/group/nhusers?hl=en.
>
>
--
You received this message because you are subscribed to the Google Groups
"nhusers" group.
To post to this group, send email to [email protected].
To unsubscribe from this group, send email to
[email protected].
For more options, visit this group at
http://groups.google.com/group/nhusers?hl=en.