我正在从传入的Type中创建一个DbSet,我需要在数据库中查询动态字段和值。使用泛型我会使用带有lambda表达式的where函数。这可以通过如下创建的标准dbSet来实现吗?
DbSet table = dataContext.Set(EntityType);
PropertyInfo propertyInfo = EntityType.GetProperty(PropertyName);
// Expression: "entity"
ParameterExpression parameter = Expression.Parameter(EntityType, "entity");
// Expression: "entity.PropertyName"
MemberExpression propertyValue = Expression.MakeMemberAccess(parameter, propertyInfo);
// Expression: "value"
object convertedValue = Convert.ChangeType(value, propertyInfo.PropertyType);
ConstantExpression rhs = Expression.Constant(convertedValue);
// Expression: "entity.PropertyName == value"
BinaryExpression equal = Expression.Equal(propertyValue, rhs);
// Expression: "entity => entity.PropertyName == value"
LambdaExpression lambda = Expression.Lambda(equal, parameter);
现在需要查询表以获取数据。
答案 0 :(得分:1)
有一个名为'System.Linq.Dynamic'的nuget包。
http://dynamiclinq.codeplex.com/
此包允许您使用字符串形成针对DbSets的语句,如下所示:
myContext.MyDbSet.Where(“PropertyName == @ 0”,“aValue”);
可以使用您在问题中建议的表达式来执行此操作,但此库可以解决所有繁重的问题。
我在以前的一个项目中使用过这个非常成功。
答案 1 :(得分:0)
您可以尝试以下内容:
public class UniqueRecordValidationAttribute : ValidationAttribute
{
public IValidationAttribute DynamicInstance { get; private set; }
public UniqueRecordValidationAttribute(Type type,
params object[] arguments )
{
DynamicInstance =
Activator.CreateInstance(type, arguments) as IValidationAttribute;
}
public override bool IsValid(object value)
{
return DynamicInstance.IsValid(value);
}
}
public class UniqueRecordValidator<C, E, P> : IValidationAttribute
where C : DataContext, new() where E : class
{
Func<E, P, bool> Check { get; set; }
public UniqueRecordValidator(Func<E, P, bool> check)
{
Check = check;
}
public bool IsValid(object value)
{
DataContext dataContext = new C();
Table<E> table = dataContext.GetTable<E>();
return table.Count(i => Check(i as E, (P)value)) == 0;
}
}
public interface IValidationAttribute
{
bool IsValid(object value);
}
和
[UniqueRecordValidation(
typeof(UniqueRecordValidator<AssetTrackingEntities, ATUser_Account, string>),
new Func<ATUser_Account, string, bool>((i, p) => i.User_Login == p))]
public string User_Name { get; set; }
这将是一个完全强类型的解决方案,但我并不感觉EF支持Func<E, P, bool>
内的Count
,因为我目前无法在此测试。但对于LINQ to objects,这段代码确实有用。
如果这不起作用,您至少可以使用泛型和dynamic LINQ来改进它:
public class UniqueRecordValidator<C, E> : IValidationAttribute
where C : DataContext, new() where E : class
{
string PropertyName { get; set; }
public UniqueRecordValidator(string propertyName)
{
PropertyName = propertyName;
}
public bool IsValid(object value)
{
DataContext dataContext = new C();
Table<E> table = dataContext.GetTable<E>();
return table.Count(PropertyName + " = @0", value) == 0;
}
}
[UniqueRecordValidation(
typeof(UniqueRecordValidator<AssetTrackingEntities, ATUser_Account>)
"User_Login")]
public string User_Login { get; set; }