Các mã sau đây được điều hành trong cơ sở dữ liệu khác nhau, Oracle:
select sysdate from dual
SQLiteselect datetime('now')
Khi làm
Session.CreateSQLQuery(cmd).UniqueResult<DateTime>()
kết quả là một DateTime khi làm việc với Oracle nhưng một chuỗi khi làm việc với SQLite .Nó giống như một lỗi trong trình điều khiển SQLite và một hack để kiểm tra kiểu trả về và làm một DateTime.Parse() nếu nó là một chuỗi. Tôi có thể làm điều đó nhưng có cách nào để NHibernate trở về đúng loại?
Tôi đang cố tìm nạp cơ sở dữ liệu hiện tại từ cơ sở dữ liệu. Nó hoạt động tốt khi sử dụng Oracle nhưng khi tôi cố gắng để làm điều đó chống lại SQLite (trong bài kiểm tra đơn vị của tôi) nó phá vỡ như ngày trở lại không phải là một DateTime nhưng một chuỗi.
Tôi đã xem giải pháp bằng cách sử dụng IUserType tùy chỉnh nhưng tôi không thể thấy cách tôi nên sử dụng trong trường hợp này. Bất kỳ đề xuất?
using System;
using System.Collections.Generic;
using NHibernate;
using NHibernate.Criterion;
using NHibernate.Dialect.Function;
namespace My.Common.Types {
public class MyNHibernateDialectException : Exception {
public MyNHibernateDialectException(string message) : base(message) { }
}
/// <summary>
/// Define all custom functions here by name. It is important that when adding a new custom sql function, that function will work
/// in all dialects supported.
/// </summary>
public static class MyDatabaseDialects {
public enum Query {
SysDate
}
/// <summary>
/// Dialect implementations will use this function to verify that they all implement the same functions.
/// </summary>
/// <param name="dialect"></param>
public static void VerifyRegistrations(this NHibernate.Dialect.Dialect dialect) {
// Verify that the required function are there
foreach (var func in Enum.GetValues(typeof(Function))) {
var enumName = func.ToString();
if (!dialect.Functions.ContainsKey(enumName)) {
throw new MyNHibernateDialectException(
string.Format("The custom function '{0}' is not defined. Did you forget it in factory '{1}'?", enumName, dialect));
}
}
}
}
/// <summary>
/// An interface to reveal more advanced functionality that is database specific
/// </summary>
public interface IDialectExtensions {
/// <summary>
/// Fetch a query specfic for the current database.
/// </summary>
ISQLQuery GetQuery(ISession session, MyDatabaseDialects.Query query);
/// <summary>
/// Fetch a parameterized query specfic for the current database.
/// </summary>
ISQLQuery GetQuery(ISession session, MyDatabaseDialects.Query query, params object[] queryParams);
}
/// <summary>
/// Class to store database specific objects except functions (which are supported by NHibernate).
/// </summary>
class DialectExtension {
private readonly Dictionary<MyDatabaseDialects.Query, string> queryDictionary = new Dictionary<MyDatabaseDialects.Query, string>();
public ISQLQuery GetQuery(ISession session, MyDatabaseDialects.Query query) {
return this.GetQuery(session, query, null);
}
public ISQLQuery GetQuery(ISession session, MyDatabaseDialects.Query query, params object[] queryParams) {
var cmd = (queryParams == null) ? queryDictionary[query] : string.Format(queryDictionary[query], queryParams);
return session.Session.CreateSQLQuery(cmd);
}
public void RegisterQuery(MyDatabaseDialects.Query query, string hqlString) {
queryDictionary.Add(query, hqlString);
}
public void VerifyQueryRegistrations() {
foreach (var query in Enum.GetValues(typeof(MyDatabaseDialects.Query))) {
if (!queryDictionary.ContainsKey((MyDatabaseDialects.Query)query)) {
throw new MyNHibernateDialectException(string.Format("The custom query '{0}' is not defined.", query.ToString()));
}
}
}
}
public class MyOracle10gDialect : NHibernate.Dialect.Oracle10gDialect, IDialectExtensions {
private readonly DialectExtension dialectExtension = new DialectExtension();
public MyOracle10gDialect() {
#region Dialect extensions
dialectExtension.RegisterQuery(MyDatabaseDialects.Query.SysDate, @"select sysdate from dual");
dialectExtension.VerifyQueryRegistrations();
#endregion Dialect extensions
}
public ISQLQuery GetQuery(ISession session, MyDatabaseDialects.Query query) {
return dialectExtension.GetQuery(session, query);
}
public ISQLQuery GetQuery(ISession session, MyDatabaseDialects.Query query, params object[] queryParams) {
return dialectExtension.GetQuery(session, query, queryParams);
}
}
public class MySqliteDialect : NHibernate.Dialect.SQLiteDialect, IDialectExtensions {
private readonly DialectExtension dialectExtension = new DialectExtension();
public MySqliteDialect() {
#region Dialect extensions
dialectExtension.RegisterQuery(MyDatabaseDialects.Query.SysDate, @"select datetime('now')");
dialectExtension.VerifyQueryRegistrations();
#endregion Dialect extensions
}
public ISQLQuery GetQuery(ISession session, MyDatabaseDialects.Query query) {
return dialectExtension.GetQuery(session, query);
}
public ISQLQuery GetQuery(ISession session, MyDatabaseDialects.Query query, params object[] queryParams) {
return dialectExtension.GetQuery(session, query, queryParams);
}
}
}
Và tôi sử dụng đoạn mã trên như thế này:
/// <summary>
/// Fetches a DialectExtensions object allowing us to have more advanced functionality that is database specific
/// </summary>
public static IDialectExtensions GetDialectExtensions(this IOperationContext operationContext) {
return Session.GetSessionImplementation().Factory.Dialect as IDialectExtensions;
}
/// <summary>
/// Get the database time by executing a raw SQL statement.
/// </summary>
public static DateTime? GetDatabaseTime() {
DateTime? result = null;
try {
result = GetDialectExtensions()
.GetQuery(Session, MyDatabaseDialects.Query.SysDate)
.UniqueResult<DateTime>();
} catch {
// SQLite will throw exception here as the result is returned as a string instead of a DateTime
}
return result;
}
Bạn có thể thêm toàn bộ ngoại lệ không? – Najera
Nó cố gắng để đúc chuỗi để một DateTime vì vậy ngoại lệ là: InvalidCastException - Cast quy định là không hợp lệ –
SQLite [đã không ngày/thời gian kiểu dữ liệu] (http://www.sqlite.org/datatype3.html#datetime) ; hàm ['datetime'] (http://www.sqlite.org/lang_datefunc.html) luôn trả về một chuỗi. –