C#Entity framework 4.0
我有一个包含10个表的数据库,其中包含2个常用列'id'和'modstamp'
访问表格中的modstamp我有一个函数
protected internal override string GetModStampinChild(int sid)
{
DBContext sq = new DBContext();
return sq.xxxx.Where(s => s.id == sid)
.Select(s => s.modstamp).SingleOrDefault().ToModStampString();
}
其中xxxx为每个表更改。 我现在正在为每张桌子重写这个功能。
有没有办法使用某种通用的“类”,我可以使用“xxxx”作为任何表格?
答案 0 :(得分:2)
首先,您需要让所有实体实现一个接口或一个包含ID
和ModStamp
属性的抽象类,让我们调用它{{ 1}}:
Stampable
此时,你需要为你的方法做的就是让它实现泛型输入:
public abstract class Stampable
{
[Key]
public int ID { get; set; }
[Required]
public string ModStamp { get; set; }
}
答案 1 :(得分:0)
如果我理解正确,您需要Set<T>
类DbContext
的属性:
首先,使用id
和modstamp
属性创建所有实体类的基类。然后:
protected internal override string GetModStampInChild<T>(int sid) where T : BaseEntity
{
using (var sq = new DbContext())
{
return sq.Set<T>.Where(s => s.id == sid)
.Select(s => s.modstamp)
.SingleOrDefault()
.ToModStampString();
}
}
但是你必须为这种方法使用代码优先范例。
答案 2 :(得分:0)
另一种选择是通过c#的部分类功能为您的实体类添加一个新属性。
所以生成的实体定义可能如下所示,注意我不知道你的ModStamp列的实际DataType是什么:
public partial class Company
{
public int Id { get; set; }
public byte[] ModStamp { get; set; }
public string Name { get; set; }
public string City { get; set; }
public string State { get; set; }
}
请注意要转换的ModStamp列。
然后添加到EF创建这样的代码的Partial.cs文件中,注意我不知道你真正想要用ModStamp值做什么:
public static class ModConverter
{
public static string ToModStampString(byte[] modStamp)
{
return BitConverter.ToString(modStamp);
}
}
public partial class Company
{
public string ModStampString
{
get
{
return ModConverter.ToModStampString(this.ModStamp);
}
}
}
然后,您必须为每个具有ModStamp列的实体手动添加新的ModStampString获取属性,就像我为公司实体所做的那样。
答案 3 :(得分:0)
这是一个使用DbContext和表达式树上的Set方法动态查询该对象的解决方案。
private Expression<Func<TArg, bool>> CreatePredicate<TArg, TPredicateField>(string fieldName, TPredicateField value)
{
ParameterExpression parameter = Expression.Parameter(typeof(TArg), "o");
MemberExpression memberExpression = Expression.Property(parameter, fieldName);
var condition = Expression.Equal(memberExpression, Expression.Constant(value));
var lambda = Expression.Lambda<Func<TArg, bool>>(condition, parameter);
return lambda;
}
private Expression<Func<TArg, TPredicateField>> CreateSelector<TArg, TPredicateField>(string fieldName)
{
ParameterExpression parameter = Expression.Parameter(typeof(TArg), "o");
Expression propertyExpr = Expression.Property(parameter, fieldName);
var lambda = Expression.Lambda<Func<TArg, TPredicateField>>(propertyExpr, parameter);
return lambda;
}
public TSelectorField GetModStamp<TEntity, TPredicateField, TSelectorField>(TPredicateField id) where TEntity : class
{
using (var ctx = new OnTheFlyEntities("Data Source=(local);Initial Catalog=AscensionBO;Integrated Security=True;MultipleActiveResultSets=True"))
{
var predicate = CreatePredicate<TEntity, TPredicateField>("Id", id);
var selector = CreateSelector<TEntity, TSelectorField>("ModStamp");
TSelectorField item = ctx.Set<TEntity>().Where(predicate).Select(selector).SingleOrDefault();
return item;
}
}
然后你可以这样称呼它:
GetModStamp<Entity2, int, string>(1)
如果您愿意只返回找到的实体,则可以删除TSelectorField,然后在检索后从项目中获取ModStamp。这将删除一个表达式树方法和一个主方法上的泛型输入。
正如其他人建议的那样,你可以去接口路由并使用那个例子,它会更简单。