我遇到以下问题 - 有限的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”)
组成如果此参数是父实体,我如何在此扩展方法中为db.Query.Where Linq方法实现谓词?
答案 0 :(得分: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 :(得分: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();
}