2014-06-16 20 views
4

我想用下面的語句來獲得與我後場的實體:NHibernate的AliasToBean變壓器協會

retVal = session.CreateCriteria(typeof(MyEntity)) 
      .CreateAlias("MyEntityProperty", "MyEntityProperty") 
      .Add(Restrictions.Eq("MyEntityProperty.Year", year)) 
      .SetProjection(
       Projections.Distinct(
        Projections.ProjectionList() 
         .Add(Projections.Property("Property1"), "Property1") 
         .Add(Projections.Property("Property2"), "Property2") 
         .Add(Projections.Property("MyEntityProperty.RegisteredUser"), "MyEntityProperty.RegisteredUser") 
         .Add(Projections.Property("MyEntityProperty.CompanyInfo"), "MyEntityProperty.CompanyInfo") 
               ) 
      ) 
      .SetResultTransformer(Transformers.AliasToBean(typeof(MyEntity))) 
      .List<MyEntity>() 
      .Cast<BaseMyEntity>(); 

myEntity所是我想要返回的實體,和MyEntityProperty是的屬性MyEntity是另一個實體(MyEntityProperty類型)。

我得到的錯誤是Could not find a setter for property 'MyEntityProperty.RegisteredUser' in class 'MyEntity'

是在AliasToBean變壓器不能處理子實體?或者還有什麼我需要做的,以使其工作?

+0

FYI:https://github.com/nhibernate/nhibernate-core/pull/1534 – quetzalcoatl

回答

19

有我的主片 ...我用它來改變任何級別的投影深度。把它和使用它像這樣:

.SetResultTransformer(new DeepTransformer<MyEntity>()) 

它可以被用於任何ValueType性質,many-to-one參考,也爲dynamic objects ...

public class DeepTransformer<TEntity> : IResultTransformer 
    where TEntity : class 
{ 
    // rows iterator 
    public object TransformTuple(object[] tuple, string[] aliases) 
    { 
     var list = new List<string>(aliases); 

     var propertyAliases = new List<string>(list); 
     var complexAliases = new List<string>(); 

     for(var i = 0; i < list.Count; i++) 
     { 
      var aliase = list[i]; 
      // Aliase with the '.' represents complex IPersistentEntity chain 
      if (aliase.Contains('.')) 
      { 
       complexAliases.Add(aliase); 
       propertyAliases[i] = null; 
      } 
     } 

     // be smart use what is already available 
     // the standard properties string, valueTypes 
     var result = Transformers 
      .AliasToBean<TEntity>() 
      .TransformTuple(tuple, propertyAliases.ToArray()); 

     TransformPersistentChain(tuple, complexAliases, result, list); 

     return result; 
    } 

    /// <summary>Iterates the Path Client.Address.City.Code </summary> 
    protected virtual void TransformPersistentChain(object[] tuple 
      , List<string> complexAliases, object result, List<string> list) 
    { 
     var entity = result as TEntity; 

     foreach (var aliase in complexAliases) 
     { 
      // the value in a tuple by index of current Aliase 
      var index = list.IndexOf(aliase); 
      var value = tuple[index]; 
      if (value.IsNull()) 
      { 
       continue; 
      } 

      // split the Path into separated parts 
      var parts = aliase.Split('.'); 
      var name = parts[0]; 

      var propertyInfo = entity.GetType() 
        .GetProperty(name, BindingFlags.NonPublic 
            | BindingFlags.Instance 
            | BindingFlags.Public); 

      object currentObject = entity; 

      var current = 1; 
      while (current < parts.Length) 
      { 
       name = parts[current]; 
       object instance = propertyInfo.GetValue(currentObject); 
       if (instance.IsNull()) 
       { 
        instance = Activator.CreateInstance(propertyInfo.PropertyType); 
        propertyInfo.SetValue(currentObject, instance); 
       } 

       propertyInfo = propertyInfo.PropertyType.GetProperty(name, BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Public); 
       currentObject = instance; 
       current++; 
      } 

      // even dynamic objects could be injected this way 
      var dictionary = currentObject as IDictionary; 
      if (dictionary.Is()) 
      { 
       dictionary[name] = value; 
      } 
      else 
      { 
       propertyInfo.SetValue(currentObject, value); 
      } 
     } 
    } 

    // convert to DISTINCT list with populated Fields 
    public System.Collections.IList TransformList(System.Collections.IList collection) 
    { 
     var results = Transformers.AliasToBean<TEntity>().TransformList(collection); 
     return results; 
    } 
} 
+0

其實我已經摸索出我讓事情比我需要的更復雜,但非常感謝您的代碼,它看起來非常有用。 – tomunderhill

+0

dictionary.Is() 這就像一個「是或不是」的東西?或者是某種空的檢查? – user99999991

+1

@ user999999928正確..這只是一個擴展,檢查null ... *(通過任何類型提供它,包括ValueTypes - 使用流暢語法的抽象)* –

1

嘛不是我做的事情比更復雜必要。

,而不是試圖設置子實體領域,所有我需要做的是參考實體領域本身:

.Add(Projections.Property("MyEntityProperty"), "MyEntityProperty") 

和NHibernate填充它的罰款。

但我很高興我問,因爲我得到了拉迪姆的非常有用的代碼:-)

+0

如果你想設置子域,該怎麼辦? – aggietech