簡體   English   中英

無法在帶有 CustomType 的查詢中轉換為 IConvertible

[英]Cannot cast to IConvertible in Query with CustomType

使用 NHibernate 會話運行此代碼時:

_session.Query<Order>().SingleOrDefault(o => o.EmployeeNumber == employeeNumber);

我收到以下異常:

Unable to cast object of type 'EmployeeNumber' to type 'System.IConvertible'.

相關代碼:

public class Order : FOAggregateRoot
{
    private readonly int _employeeNumber;
    public virtual EmployeeNumber EmployeeNumber => (EmployeeNumber)_employeeNumber;
    private readonly IList<OrderLine> _products;
    public virtual IReadOnlyList<OrderLine> Products => _products.ToList();
    public virtual Price Total => (Price)_products.Sum(line => line.Total);

    public Order(EmployeeNumber employeeNumber) : base(Guid.NewGuid())
    {
        _products = new List<OrderLine>();
        _employeeNumber = employeeNumber;
    }

    protected Order() { }
}

public sealed class EmployeeNumber : SingleValueObject<int>
{
    public EmployeeNumber(int value)
    {
        Value = value;
    }

    public static implicit operator int(EmployeeNumber number)
    {
        return number.Value;
    }

    public static explicit operator EmployeeNumber(int number)
    {
        return new EmployeeNumber(number);
    }
}

public class OrderMap : ClassMap<Order>
{
    public OrderMap()
    {
        Id(Entity.Expressions<Order>.Id);
        Map(x => x.Uid);
        Map(x => x.EmployeeNumber)
            .Unique()
            .CustomType<int>().Access.CamelCaseField(Prefix.Underscore);
        HasMany(x => x.Products)
            .Inverse()
            .Cascade.All()
            .Not.LazyLoad();
    }
}

我有點“理解”為什么會發生這個異常,我可以通過實現IConvertible (我不想要在我的值對象中)或明確地將employeeNumber IConvertibleint來解決它。

但是,我本來希望這段代碼開箱即用,特別是因為我在EmployeeNumber定義了一個隱式轉換為int operator ,但是 NHibernate 似乎沒有使用它。

在這種情況下,是否可以通知 NHibernate 使用此operator

是否存在任何其他解決方案? (理想情況下,如果它編譯,它會運行)

我注定要使用兩個第一個解決方案(IConvertible/explicit cast)中的一個嗎?

解決方案是為我的不同值對象創建我自己的自定義類型:

public sealed class EmployeeNumberUserType : SingleValueObjectType<EmployeeNumber>
{
    protected override NullableType PrimitiveType => NHibernateUtil.Int32;
}

public abstract class SingleValueObjectType<TValueObject> : IUserType where TValueObject : class
{
    public SqlType[] SqlTypes => new[] { PrimitiveType.SqlType };

    public Type ReturnedType => typeof(TValueObject);

    public bool IsMutable => false;

    public object Assemble(object cached, object owner) => cached;

    public object DeepCopy(object value) => value;

    public object Disassemble(object value) => value;

    public new bool Equals(object x, object y) => x?.Equals(y) ?? y?.Equals(x) ?? true;

    public int GetHashCode(object x) => x?.GetHashCode() ?? 0;

    public object NullSafeGet(DbDataReader rs, string[] names, ISessionImplementor session, object owner)
    {
        var obj = PrimitiveType.NullSafeGet(rs, names[0], session, owner);
        if (obj == null) return null;
        else return Activator.CreateInstance(typeof(TValueObject), obj);
    }

    public void NullSafeSet(DbCommand cmd, object value, int index, ISessionImplementor session)
    {
        if (value == null) cmd.Parameters[index].Value = DBNull.Value;
        else cmd.Parameters[index].Value = value.GetType()
                                                .GetProperty("Value", BindingFlags.Instance | BindingFlags.NonPublic)
                                                .GetValue(value);
    }

    public object Replace(object original, object target, object owner) => original;

    protected abstract NullableType PrimitiveType { get; }
}

並在映射中明確使用此自定義類型:

public class OrderMap : ClassMap<Order>
{
    public OrderMap()
    {
        Id(Entity.Expressions<Order>.Id);
        Map(x => x.EmployeeNumber)
            .Unique()
            .CustomType<EmployeeNumberUserType>();
    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM