【问题标题】:Writing a predicate for Linq (2Sqlite)为 Linq 编写谓词(2Sqlite)
【发布时间】:2013-10-01 12:54:40
【问题描述】:

我有以下问题 - 将基础设施耦合到域对象的有限 ORM。

请注意,这是一个 Windows 应用商店应用程序,反射 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”)组成

假设 this 参数是父实体,如何在这个扩展方法中实现 db.Query.Where Linq 方法的谓词?

【问题讨论】:

    标签: c# .net linq c#-4.0 predicate


    【解决方案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();
    

    【讨论】:

      【解决方案2】:

      这对我有用,但不幸的是 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();
          }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-04-16
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多