2011-09-20 23 views
8

Tôi cần phải so sánh hai thuộc tính DateTime trong một truy vấn LINQ, tương tự như hình dưới đây -Nhibernate LINQ DateTime.AddDay không hoạt động

var patients = from c in session.Query<Patient>() where c.DateAdded.AddDays(1) < c.AdmitDate select c; 

khi tôi chạy truy vấn tôi nhận được ngoại lệ này: System. NotSupportedException { "AddDays System.DateTime (Double)"}

tại NHibernate.Linq.Visitors.HqlGeneratorExpressionTreeVisitor.VisitMethodCallExpression (MethodCallExpression expression)

Tôi đã xem bài viết của Fabio trên số http://fabiomaulo.blogspot.com/2010/07/nhibernate-linq-provider-exten ... nhưng treeBuilder không có bất kỳ chức năng nào cụ thể cho các so sánh ngày DateTime.

Đây là mã cho mẫu. Để thực hiện điều này, hãy cài đặt các gói NuGet cho FluentNhibernate và SQLite.

using System; 
using System.Collections.Generic; 
using System.Data.SQLite; 
using System.IO; 
using System.Linq; 
using System.Text; 
using FluentNHibernate.Cfg; 
using FluentNHibernate.Cfg.Db; 
using FluentNHibernate.Mapping; 
using NHibernate; 
using NHibernate.Cfg; 
using NHibernate.Tool.hbm2ddl; 
using NHibernate.Linq; 

namespace ConsoleApplication1 
{ 
    class Program 
    { 
      private static Configuration _config; 

      static void Main(string[] args) 
      { 
        var sessionFactory = CreateSessionFactory(); 
        using (var session = sessionFactory.OpenSession()) 
        { 
          BuildSchema(session); 
          using(var transaction = session.BeginTransaction()) 
          { 
            var foo = new Patient 
            { 
              Name = "Foo", 
              Sex = Gender.Male, 
              DateAdded = new DateTime(2009, 1, 1), 
              AdmitDate = new DateTime(2009, 1, 2) 
            }; 
            var bar = new Patient 
            { 
              Name = "Bar", 
              Sex = Gender.Female, 
              DateAdded = new DateTime(2009, 1, 1), 
              AdmitDate = new DateTime(2009, 1, 2) 
            }; 
            session.SaveOrUpdate(foo); 
            session.SaveOrUpdate(bar); 
            transaction.Commit(); 
          } 
          session.Flush(); 

          using (session.BeginTransaction()) 
          { 
            var cats = from c in session.Query<Patient>() where 
c.DateAdded.AddDays(1) < c.AdmitDate select c; 
            foreach (var cat in cats) 
            { 
              Console.WriteLine("patient name {0}, sex {1}", cat.Name, 
cat.Sex); 
            } 
          } 
        } 
        Console.ReadKey(); 
      } 

      private static ISessionFactory CreateSessionFactory() 
      { 
        return Fluently.Configure() 
         .Database(
          SQLiteConfiguration.Standard.InMemory() 
        ) 
         .Mappings(m => 
          m.FluentMappings.AddFromAssemblyOf<Program>()) 
         .ExposeConfiguration(c => _config = c) 
         .BuildSessionFactory(); 
      } 

      private static void BuildSchema(ISession session) 
      { 
        new SchemaExport(_config) 
         .Execute(true, true, false, session.Connection, null); 
      } 
    } 

    public class PatientMap : ClassMap<Patient> 
    { 
      public PatientMap() 
      { 
        Id(x => x.Id); 
        Map(x => x.Name) 
         .Length(16) 
         .Not.Nullable(); 
        Map(x => x.Sex); 
        Map(x => x.DateAdded); 
        Map(x => x.AdmitDate); 
      } 
    } 

    public class Patient 
    { 
      public virtual int Id { get; set; } 
      public virtual string Name { get; set; } 
      public virtual Gender Sex { get; set; } 
      public virtual DateTime DateAdded { get; set; } 
      public virtual DateTime AdmitDate { get; set; } 
    } 

    public enum Gender 
    { 
      Male, 
      Female 
    } 

Cảm ơn, Vikram

+0

Hình như nó đã được báo cáo ở đây: https://nhibernate.jira.com/ browse/NH-2849 Bạn đã thử sử dụng 'QueryOver' thay thế? – mxmissile

Trả lời

10

trả lời cho câu hỏi trên:

using System; 
using System.Linq; 
using System.Reflection; 
using FluentNHibernate.Cfg; 
using FluentNHibernate.Cfg.Db; 
using FluentNHibernate.Mapping; 
using NHibernate; 
using NHibernate.Cfg; 
using NHibernate.Dialect; 
using NHibernate.Dialect.Function; 
using NHibernate.Hql.Ast; 
using NHibernate.Linq.Functions; 
using NHibernate.Tool.hbm2ddl; 
using NHibernate.Linq; 
using System.Collections.ObjectModel; 
using System.Linq.Expressions; 
using NHibernate.Linq.Visitors; 
using NHibernate.Cfg.Loquacious; 

namespace ConsoleApplication1 
{ 
class Program 
{ 
    private static Configuration _config; 

    static void Main(string[] args) 
    {App_Start.NHibernateProfilerBootstrapper.PreStart(); 

     var sessionFactory = CreateSessionFactory(); 
     using (var session = sessionFactory.OpenSession()) 
     { 
      BuildSchema(session); 
      using(var transaction = session.BeginTransaction()) 
      { 
       var foo = new Patient 
       { 
        Name = "Foo", 
        Sex = Gender.Male, 
        DateAdded = new DateTime(2009, 1, 4), 
        AdmitDate = new DateTime(2009, 1, 6) 
       }; 
       var bar = new Patient 
       { 
        Name = "Bar", 
        Sex = Gender.Female, 
        DateAdded = new DateTime(2009, 1, 1), 
        AdmitDate = new DateTime(2009, 1, 2) 
       }; 
       session.SaveOrUpdate(foo); 
       session.SaveOrUpdate(bar); 
       transaction.Commit(); 
      } 
      session.Flush(); 

      using (session.BeginTransaction()) 
      { 
       //x.PatientVisit.AdmitDate.Value.Date == x.DateAdded.Date 
       var patients = from c in session.Query<Patient>() where c.DateAdded.AddDays(1) < c.AdmitDate.Value select c; 
       foreach (var cat in patients) 
       { 
        Console.WriteLine("patient name {0}, sex {1}", cat.Name, cat.Sex); 
       } 
      } 
     } 
     Console.ReadKey(); 
    } 

    private static ISessionFactory CreateSessionFactory() 
    { 
     return Fluently.Configure() 
      .Database(
       MsSqlConfiguration.MsSql2008.Dialect<CustomDialect>() 
        .ConnectionString("Data Source=.;Initial Catalog=testdb;Integrated Security=True;Connection Reset=false") 
      ) 
      .Mappings(m => 
         m.FluentMappings.AddFromAssemblyOf<Program>()) 
      .ExposeConfiguration(c => 
            { 
             c.LinqToHqlGeneratorsRegistry<ExtendedLinqtoHqlGeneratorsRegistry>(); 
             _config = c; 
            }) 
      .BuildSessionFactory(); 
    } 

    private static void BuildSchema(ISession session) 
    { 
     new SchemaExport(_config) 
      .Execute(true, true, false, session.Connection, null); 
    } 
} 

public class PatientMap : ClassMap<Patient> 
{ 
    public PatientMap() 
    { 
     Id(x => x.Id); 
     Map(x => x.Name) 
      .Length(16) 
      .Not.Nullable(); 
     Map(x => x.Sex); 
     Map(x => x.DateAdded); 
     Map(x => x.AdmitDate); 
    } 
} 

public class Patient 
{ 
    public virtual int Id { get; set; } 
    public virtual string Name { get; set; } 
    public virtual Gender Sex { get; set; } 
    public virtual DateTimeOffset DateAdded { get; set; } 
    public virtual DateTime? AdmitDate { get; set; } 
} 

public enum Gender 
{ 
    Male, 
    Female 
} 

public class ExtendedLinqtoHqlGeneratorsRegistry : DefaultLinqToHqlGeneratorsRegistry 
{ 
    public ExtendedLinqtoHqlGeneratorsRegistry() 
    { 
     this.Merge(new AddDaysGenerator()); 
    } 
} 

public class AddDaysGenerator : BaseHqlGeneratorForMethod 
{ 
    public AddDaysGenerator() 
    { 
     SupportedMethods = new[] { 
      ReflectionHelper.GetMethodDefinition<DateTimeOffset?>(d => d.Value.AddDays((double)0)) 
     }; 
    } 

    public override HqlTreeNode BuildHql(MethodInfo method, Expression targetObject, ReadOnlyCollection<Expression> arguments, HqlTreeBuilder treeBuilder, IHqlExpressionVisitor visitor) 
    { 
     return treeBuilder.MethodCall("AddDays", 
             visitor.Visit(targetObject).AsExpression(), 
             visitor.Visit(arguments[0]).AsExpression() 
            ); 
    } 
} 

public class CustomDialect : MsSql2008Dialect 
{ 
    public CustomDialect() 
    { 
     RegisterFunction(
      "AddDays", 
      new SQLFunctionTemplate(
       NHibernateUtil.DateTime, 
       "dateadd(day,?2,?1)" 
       ) 
      ); 
    } 
} 

}

+1

Xin chào ... Làm cách nào tôi có thể làm điều đó với ánh xạ NHibernate được nhúng bằng mã cấu hình? – Junior

+0

Điều này dường như có nhiều hứa hẹn. Làm thế nào tôi có thể kết hợp điều này với cấu hình * .xml? – user734929

Các vấn đề liên quan