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, ) =&gt; (Equal(element.CategoryID, p1))), ),
> Quote((element,
> > > ) =&gt; (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.

Reply via email to