2013-10-01 2 views
2

У меня есть следующая проблема - ограниченная ORM, которая связывает инфраструктуру с объектами домена.Написание предиката для Linq (2Sqlite)

Пожалуйста, обратите внимание, что это магазин приложений для Windows и Reflection API отличается от стандартного .Net

Например, я должен вручную реализовать навигационные свойства (отношения в коде), как это (при условии, у меня есть книга агрегат с одним -в-многих ребенок коллекция глав):

List<Chapters> Chapters 
{get {return db.Query<Chapters>.Where(b => b.BookId == this.Id);}} 

Я хочу, чтобы уменьшить это взаимодействие быть средством общего метода расширения, который будет извлекать дочерние объекты для родителей, как

IEnumerable<T> GetChildren<TParent,TChild>(this TParent parent) 
                where TParent, TChild : Entity 

Я могу предположить, что все объекты имеют первичное свойство Id ключа и внешний ключ состоят из названия Родитель сущности и Id («BookID»)

Как реализовать предикат для метода db.Query.Where Linq в этот метод расширения, если этот параметр является родительским объектом?

ответ

1

Что-то вроде так (упрощенный вариант):

public static TChild GetHierarchyChild<TParent, TChild>(this TParent parent) 
     { 
      var pType = typeof(TParent); 
      var chType = typeof(TChild); 

      var chPropInfo = pType 
            .GetProperties() 
            .FirstOrDefault(p => p.PropertyType == chType); 
      if (chPropInfo == null) 
      { 
       return default(TChild); 

      } 

      return (TChild)chPropInfo.GetValue(parent); 
     } 

    public class A 
    { 
     public IEnumerable<B> Bs 
     { 
      get 
      { 
       return new[] { new B(1) }; 
      } 
     } 
    } 

    public class B 
    { 
     public B(int id) 
     { 
      Id = id; 
     } 

     public int Id { get; protected set; } 
    } 

пример:

var a = new A(); 
var bs = GetHierarchyChild<A, IEnumerable<B>>(a); 
bs.ToString(); 
1

Это работает для меня, но, к сожалению, Sqlite-Net не поддерживает выражения такого типа в его реализации Linq2Db. Он вылетает из последнего утверждения. Мне придется переписать эту часть на SQL.

 private const string keyName = "Id"; 

    public static async Task<IEnumerable<TChild>> GetChildrenAsync<TParent, TChild>(this TParent parent) 
     where TParent : Entity 
     where TChild : Entity, new() 
    { 
     var parentType = typeof (TParent); 
     var parentName = parentType.GetTypeInfo().Name; 
     var parentKeyValue = (int)parentType.GetRuntimeProperty(keyName).GetValue(parent); 
     var foreignKeyName = String.Format("{0}{1}", parentName, keyName); 
     var childProperty = typeof(TChild).GetRuntimeProperty(foreignKeyName); 

     var connection = DbConnection.Current; 
     var query = connection.Table<TChild>().Where(c => (int)childProperty.GetValue(c) == parentKeyValue); 
     return await query.ToListAsync(); 
    } 
Смежные вопросы