У меня есть несколько методов с общим шаблоном, я хочу написать общую функцию, которая будет принимать имя столбца в качестве входных данных и давать тот же результат.
private void Query138()
{
var products = (from p in _context.Products
where p.Manufacturer == null
select p);
foreach (var productItem in products)
{
productItem.Manufacturer = string.Empty;
_context.UpdateProduct(productItem);
}
}
private void Query139()
{
var products = (from p in _context.Products
where p.ModelNumber == null
select p);
foreach (var productItem in products)
{
productItem.ModelNumber = string.Empty;
_context.UpdateProduct(productItem);
}
}
Я хочу написать общую функцию, которая будет принимать имя столбца в качестве входных данных для вышеуказанных методов.
Пример:
private void Update(Expression<Fun<T,string>> pred = null)
{
//use the input column to select the data
//use the input column to set the new value and update
}





Для этого вам понадобятся два выражения. Один для получения значения, а другой - для его установки.
private void Update(Expression<Func<T, string>> getter, Expression<Action<T, string>> setter)
{
var products = (from p in _context.Products
where getter(p) == null
select p);
foreach (var productItem in products)
{
setter(productItem, string.Empty);
_context.UpdateProduct(productItem);
}
}
Таким образом, вы можете использовать i => i.[Your Attribute] и (i, o) => i.[Your Attribute] = o для вызова вашей функции:
Update(i => i.[Your Attribute],(i, o) => i.[Your Attribute] = o);
Или в вашем случае:
Update(i => i.Manufacturer,(i, o) => i.Manufacturer = o);
Update(i => i.ModelNumber,(i, o) => i.ModelNumber = o);
Вы можете указать геттер и использовать его для создания сеттера. Этого можно добиться следующим образом:
private void Update(Expression<Func<Product, string>> getExpr)
{
var value = Expression.Parameter(typeof(string), "value");
var setExpr = Expression.Lambda<Action<Product, string>>(
Expression.Assign(getExpr.Body, value), getExpr.Parameters[0], value);
Func<Product, string> getter = getExpr.Compile();
Action<Product, string> setter = setExpr.Compile();
var products = (from p in _context.Products
where getter(p) == null
select p);
foreach (var productItem in products)
{
setter(productItem, string.Empty);
_context.UpdateProduct(productItem);
}
}
А потом позвонил так:
Update( x => x.ModelNumber );
Исключение LINQ to SQL: метод 'System.Object DynamicInvoke (System.Object [])' не поддерживает преобразование в SQL. Вероятно, работать с LINQ to Entities.
Это должно работать:
class SomeClass
{
public string prop1 { get; set; }
public string prop2 { get; set; }
}
///...
private void Update<T, TReturn>(Expression<Func<T, TReturn>> expression)
{
MemberExpression body = (MemberExpression)expression.Body;
var propName = body.Member.Name;
var prop = typeof(SomeClass).GetProperty(propName);
var products = (from p in contextProds
where prop.GetValue(p) == null
select p);
///...
}
Применение:
Update((SomeClass s) => s.prop1);
Update((SomeClass s) => s.prop2);
Где contextProds похож на тип List<SomeClass>.
Также вы можете посетить это: Получить название свойства в виде строки.
это, вероятно, сработает для LINQ to Entities. Я получаю исключение в LINQ to SQL: метод 'System.Object GetValue (System.Object)' не поддерживает перевод в SQL.
Ты смотрел это, @ sudhAnsu63? stackoverflow.com/questions/22104050/…
Вместо получателя
Funcвам лучше собратьExpression<Product, bool>и использовать его непосредственно в_context.Products.Where. То, что вы предлагаете в настоящее время, приведет к извлечению всей таблицы и выполнению фильтрации на стороне клиента.