动态将字段名称和值传递给linq

时间:2019-07-18 15:40:02

标签: c# linq

我希望能够将FieldName作为字符串传递到更新表的Method中。我已经看过Linq.Expressions了,但是这似乎并没有显示我需要的有关字段Name和dataType的所有详细信息,并且我真的不想通过直接执行sql命令的现有字符串生成器解决方案。

    public static Main(string[] args)
    {
        UpdateLicenceField(2284, "laststoragefullalert", DateTime.Now);
        UpdateLicenceField(2284, "numberofalerts", int(tooMany);
        UpdateLicenceField(2284, "lastalertmessage", "Oops");
    }

    public static void UpdateLicenceField(int LicenceID, string FieldName, object value)
    {
        using (myContext db = new MyContext())
        {
            Licence licence = db.Licence.Where(x => x.ID == LicenceID && 
                  x.Deleted == false).FirstOrDefault();
            // so db.Licence has fields .laststoragefullalert .numberofalerts .lastalertmessage 
            // (in real life this has hundred of settings and we very often just want to update one)
            // I'm tring to get a single Method that will act dynamically like the current ADO function that creates a SQL string and executes that. 
            // 1. check that the FieldName type is the same type as the object passed in value.
            // 2. update that FieldName with value and Saves the Licence table.

        }

    }

2 个答案:

答案 0 :(得分:0)

您可以使用https://github.com/StefH/System.Linq.Dynamic.Core中的“ System.Linq.Dynamic.Core”库并使用:

Licence licence = db.Licence.Where(FieldName + "==@0", fieldValue).FirstOrDefault();

或使用如下方法:

public Expression<Func<TEntity, bool>> GetPredicate(string methodName, string propertyName, string propertyValue)
{
    var parameterExp = Expression.Parameter(typeof(TEntity), "type");
    var propertyExp = Expression.Property(parameterExp, propertyName);
    MethodInfo method = typeof(string).GetMethod(methodName, new[] { typeof(string) });
    if (method == null)
    {
        var containsMethods = typeof(Enumerable).GetMethods(BindingFlags.Static | BindingFlags.Public).Where(m => m.Name == methodName);
        foreach (var m in containsMethods)
        {
            if (m.GetParameters().Count() == 2)
            {
                method = m;
                break;
            }
        }
    }
    var someValue = Expression.Constant(propertyValue, typeof(string));
    var containsMethodExp = Expression.Call(propertyExp, method, someValue);

    return Expression.Lambda<Func<TEntity, bool>>(containsMethodExp, parameterExp);
}

Licence licence = db.Licence.Where(GetPredicate("Contains", fieldName, fieldValue)).FirstOrDefault();

希望对您有帮助。

答案 1 :(得分:0)

非常感谢您的回复。我使用了Renan和Roberto的回复中的一些内容,我将它们组合在一起完成了工作。以这种方式进行更新显然并不理想,但这不是在自动化过程中使用类似代码的50或60个功能。仍然需要添加错误检查和验证,但这会大大减少我的代码库。
再次感谢格伦。

    public static int Main(string[] args)
    {
        UpdateLicenceField(2284, "LastStorageFullAlert", DateTime.Now);
        UpdateLicenceField(2284, "IsProcessing", true);
        UpdateLicenceField(2284, "RegSource", "this is a string");
        UpdateLicenceField(2284, "ProcessFilesDelay", 200);

        return 1;
    }

    public static void UpdateLicenceField(int LicenceID, string Field, object Value)
    {
        using (BACCloudModel BACdb = new BACCloudModel())
        {
            Licence licence = BACdb.Licence.Where(x => x.ID == LicenceID && x.Deleted == false).FirstOrDefault();
            if (licence != null)
            {
                var fieldvalue = licence.GetType().GetProperty(Field);
                var ftype = fieldvalue.PropertyType;
                var vtype = Value.GetType();

                if (ftype == vtype)
                {
                    object[] Values = { Value };  
                    licence.GetType().GetProperty(Field).SetMethod.Invoke(licence, Values);
                    BACdb.SaveChanges();
                }
            }
        }
    }