簡體   English   中英

如何將屬性值轉換合並到NHibernate QueryOver .SelectList?

[英]How to incorporate property value conversion into NHibernate QueryOver .SelectList?

我希望將屬性值轉換合並到我的QueryOver查詢中。

我喜歡在查詢對象模式之后編寫查詢,直接生成MVC視圖模型。 在我的視圖模型中,我嘗試使用盡可能簡單的屬性類型,將轉換復雜性保留在視圖和控制器之外。 這意味着有時候,我需要將一種類型轉換為另一種類型,例如將日期轉換為字符串。

有人可能會爭辯說,這種轉換應該在視圖中執行,但由於我的大多數視圖模型都直接轉換為JSON對象,這會導致轉換變得更加麻煩。 在JavaScript中執行日期到字符串轉換充其量是有問題的,我的JSON轉換器不夠靈活。

這是我正在做的一個例子:

// Entity.
public class Customer
{
    public int Id { get; set; }
    public string Name { get; set; }
    public DateTimeOffset DateCreated { get; set; }
}

// View model.
public class CustomerViewModel
{
    public string Name { get; set; }
    public string DateCreated { get; set; } // Note the string type here.
}

// Query.
CustomerViewModel model = null;

List<CustomerViewModel> result = Session.QueryOver<Customer>()
    .SelectList(list => list
        .Select(n => n.Name).WithAlias(() => model.Name)
        .Select(n => n.DateCreated).WithAlias(() => model.DateCreated))
    .TransformUsing(Transformers.AliasToBean<CustomerViewModel>());
    .Future<CustomerViewModel>()
    .ToList();

運行查詢代碼時,拋出以下異常:

Object of type 'System.DateTimeOffset' cannot be converted to type 'System.String'.

顯然,這是因為以下幾行:

.Select(n => n.DateCreated).WithAlias(() => model.DateCreated))

所以問題是:如何將日期轉換為字符串轉換為查詢?

我不想在執行查詢后執行轉換,因為在轉換它們之前我需要一個額外的中間類來存儲結果。

List<CustomerViewModel> result = Session.QueryOver<Customer>(() => customerAlias)
    .SelectList(list => list
        .Select(n => customerAlias.Name).WithAlias(() => model.Name)
        // I'm not sure if customerAlias works here or why you have declared it at all
        .Select(Projections.Cast(NHibernateUtil.String, Projections.Property<Customer>(c => c.DateCreated))).WithAlias(() => model.DateCreated))
    .TransformUsing(Transformers.AliasToBean<CustomerViewModel>());
    .Future<CustomerViewModel>()
    .ToList();

應該工作但不幸的是沒有給你任何控制字符串的格式。 我通過在模型上定義一個私有屬性來處理類似的問題,該屬性將數據保存為正確的類型,並使用字符串屬性來返回格式化的值,即:

public class CustomerViewModel
{
    public string Name { get; set; }
    private DateTime DateCreatedImpl { get; set; }
    public string DateCreated { get { return DateCreatedImpl.ToString(); }}
}

這有幾個優點,但可能不適合您的JSON轉換器。 您的轉換器是否具有允許其忽略私有屬性的設置或屬性?

我今天遇到了同樣的問題,看到了這個帖子。 我繼續創建了自己的變換器,可以使用Converter函數來處理每個屬性的類型轉換。

這是Transformer類。

public class AliasToDTOTransformer<D> : IResultTransformer where D: class, new()
{
    //Keep a dictionary of converts from Source -> Dest types...
    private readonly IDictionary<Tuple<Type, Type>, Func<object, object>> _converters;

    public AliasToDTOTransformer()
    {
        _converters = _converters = new Dictionary<Tuple<Type, Type>, Func<object, object>>();
    }

    public void AddConverter<S,R>(Func<S,R> converter)
    {
         _converters[new Tuple<Type, Type>(typeof (S), typeof (R))] = s => (object) converter((S) s);
    }
    public object TransformTuple(object[] tuple, string[] aliases)
    {
        var dto = new D();
        for (var i = 0; i < aliases.Length; i++)
        {
            var propinfo = dto.GetType().GetProperty(aliases[i]);
            if (propinfo == null) continue;
            var valueToSet = ConvertValue(propinfo.PropertyType, tuple[i]);
            propinfo.SetValue(dto, valueToSet, null);
        }
        return dto;
    }
    private object ConvertValue(Type destinationType, object sourceValue)
    {
        //Approximate default(T) here
        if (sourceValue == null)
            return destinationType.IsValueType ? Activator.CreateInstance(destinationType) : null;

        var sourceType = sourceValue.GetType();
        var tuple = new Tuple<Type, Type>(sourceType, destinationType);
        if (_converters.ContainsKey(tuple))
        {
            var func = _converters[tuple];
            return Convert.ChangeType(func.Invoke(sourceValue), destinationType);
        }

        if (destinationType.IsAssignableFrom(sourceType))
            return sourceValue;

        return Convert.ToString(sourceValue); // I dunno... maybe throw an exception here instead?
    }

    public IList TransformList(IList collection)
    {
        return collection;
    }

以下是我如何使用它,首先是我的DTO:

public class EventDetailDTO : DescriptionDTO
{
    public string Code { get; set; }
    public string Start { get; set; }
    public string End { get; set; }
    public int Status { get; set; }

    public string Comment { get; set; }
    public int Client { get; set; }
    public int BreakMinutes { get; set; }
    public int CanBeViewedBy { get; set; } 
}

稍后當我調用我的查詢時,它將Start和End作為DateTime值返回。 這就是我實際使用轉換器的方式。

var transformer = new AliasToDTOTransformer<EventDetailDTO>();
transformer.AddConverter((DateTime d) => d.ToString("g"));

希望這可以幫助。

暫無
暫無

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

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