То, что я видел, было сделано примерно так:
public static TEntity GetOrCreate<TEntity, TPKey>(TPKey pid, SyncDBCataContext db, Func<int, TEntity> create){...}
Func был бы методом, который создает сущность, поэтому вы могли бы встроить его, когда вызываете эту функцию, или вы могли бы извлечь это и жестко прописать, как создается сущность, как вы сделали в своем вопросе.
Вот метод, который получит по id:
public T GetById<TEntity, TPKey>(TPKey id, DataContext context) where TEntity : class
{
MetaTable metaTable = context.Mapping.GetTable(typeof(TEntity));
MetaDataMember primaryKeyMetaDataMember = metaTable.RowType.DataMembers.SingleOrDefault(d => d.IsPrimaryKey);
return context.GetTable<TEntity>().SingleOrDefault(GetEqualityLambdaExpression<TEntity>(primaryKeyMetaDataMember.Name, id));
}
Вот метод, который создаст выражение для фильтра, необходимого для метода get by id:
public Expression<Func<T, bool>> GetEqualityLambdaExpression<T>(string fieldName, object constantValue)
{
ParameterExpression param = Expression.Parameter(typeof(T), "e");
Expression<Func<T, bool>> expression = Expression.Lambda<Func<T, bool>>(
Expression.Equal(Expression.Property(param, fieldName),
Expression.Constant(constantValue)),
new ParameterExpression[] { param });
return expression;
}
Как вы можете видеть, есть некоторое использование отражения. Если производительность представляет собой серьезную проблему, вы можете внедрить своего рода кэширование, чтобы уменьшить накладные расходы в будущих вызовах.