从数据库中获取字段值的动态LINQ查询

7

这是否可能呢?

Public String Get_Filed_By_Id(string table_Name,String Field_Name,string PK_val)
{
    string strRes="";
    using(mydbcontext db=new mydbcontext())
    {
      var x=db.table_Name.Where(p=>p.Id=PK_val).FirstOrDefault().Field_Name;
      strRes=Convert.Tostring(x);
    }
 return strRes;
}

或者

var x=(from o in db.table_Name where o.Id=PK_val select o.Field_Name).FirstOrDefault();

在这里,我将传递Table_NameColumn_Name和条件值(PK_val),以获取在特定条件(Id=Pk_val)下从Table_Name获取Column_Name的数据。

这可行吗?


如果你需要这种功能,首先想到的是反射(但不在IQueryable内):var tableItem = db.table_Name.Where(p => p.Id = PK_val).FirstOrDefault(); var x = tableItem.GetType().GetProperty(FieldName).GetValue(tabelItem, null); - Den
你考虑过使用仓储模式吗? - Arash
@Arashjo 不好意思,你能告诉我怎么做吗?可以给个答案吗? - A_Sk
user3540365,请稍等片刻。 - Arash
4个回答

9

这是可能的吗?

是的,它是可以实现的。

首先,我们需要一些帮助工具:

using System;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;

namespace YourNamespace
{
    internal static class DbHelpers
    {
        public static object GetColumnById(this object dbContext, string tableName, string columnName, object id)
        {
            var table = (IQueryable)dbContext.GetType().GetProperty(tableName).GetValue(dbContext, null);
            var row = Expression.Parameter(table.ElementType, "row");
            var filter = Expression.Lambda(Expression.Equal(Expression.Property(row, "Id"), Expression.Constant(id)), row);
            var column = Expression.Property(row, columnName);
            var selector = Expression.Lambda(column, row);
            var query = Call(Where.MakeGenericMethod(row.Type), table, filter);
            query = Call(Select.MakeGenericMethod(row.Type, column.Type), query, selector);
            var value = Call(FirstOrDefault.MakeGenericMethod(column.Type), query);
            return value;
        }
        private static readonly MethodInfo Select = GetGenericMethodDefinition<
            Func<IQueryable<object>, Expression<Func<object, object>>, IQueryable<object>>>((source, selector) =>
            Queryable.Select(source, selector));
        private static readonly MethodInfo Where = GetGenericMethodDefinition<
            Func<IQueryable<object>, Expression<Func<object, bool>>, object>>((source, predicate) =>
            Queryable.Where(source, predicate));
        private static readonly MethodInfo FirstOrDefault = GetGenericMethodDefinition<
            Func<IQueryable<object>, object>>(source =>
            Queryable.FirstOrDefault(source));
        private static MethodInfo GetGenericMethodDefinition<TDelegate>(Expression<TDelegate> e)
        {
            return ((MethodCallExpression)e.Body).Method.GetGenericMethodDefinition();
        }
        private static object Call(MethodInfo method, params object[] parameters)
        {
            return method.Invoke(null, parameters);
        }
    }
}

现在是您的函数:

public string Get_Field_By_Id(string table_Name, string field_Name, string PK_val)
{
    using (var db = new mydbcontext())
        return Convert.ToString(db.GetColumnById(table_Name, field_Name, PK_val));
}

1
实际上,使用EntityFramework不太可能实现(据我所知)。如果您只需要通过字段名称获取字段,则可以使用@Den提出的解决方案。但是,您还想将表名作为参数指定。因此,我建议您使用标准的Sql Connector api,并使用您提供的参数构建查询字符串。
请查看此链接以了解标准sql连接器api的用法。

1
我也曾有过这个问题,我知道这不完全是你想要的,你需要编写更多的代码,但它比你想要编写的代码要干净得多。 使用存储库模式
对于每个表格,您都应该有一个模型类和存储库类。
考虑以下代码(这段代码来自我的一个项目)
这是我的评论表(可以是带有或不带有导航属性的任何内容)
  public sealed class Comment
{
    public string CommentText { get; set; }
    public DateTime PostDate { get; set; }
    public int PostId { get; set; }
    public int? PageId { get; set; }
    public Page Page { get; set; }
    public User User { get; set; }
    public string UserId { get; set; }
    public int? ParentId { get; set; }
    public Comment[] ChildComments { get; set; }
}  

代码库评论

  public sealed class CommentRepository : BaseRepository<Comment>
{
    public CommentRepository(BabySitterContext context)
        : base(context)
    {
    }
}  

还需要一个基类,您可以在其中发送带有表名(这里是model)和字段的查询(您可以扩展该类以获取更多功能)。

public class BaseRepository<T> where T : class
{
    protected BabySitterContext Context;
    private readonly PluralizationService _pluralizer = PluralizationService.CreateService(CultureInfo.GetCultureInfo("en"));
    public BaseRepository(BabySitterContext context)
    {
        this.Context = context;
    }
    public bool Add(T t)
    {
        Context.Set<T>().Add(t);
        Context.SaveChanges();
        return true;
    }
    public bool Update(T t)
    {
        var entityName = GetEntityName<T>();

        object originalItem;
        var key = ((IObjectContextAdapter)Context).ObjectContext.CreateEntityKey(entityName, t);
        if (((IObjectContextAdapter)Context).ObjectContext.TryGetObjectByKey(key, out originalItem))
        {
            ((IObjectContextAdapter)Context).ObjectContext.ApplyCurrentValues(key.EntitySetName, t);
        }
        Context.SaveChanges();
        return true;
    }
    public void Attach(T t)
    {
        if (t == null)
        {
            throw new ArgumentNullException("t");
        }

        Context.Set<T>().Attach(t);
        Context.SaveChanges();
    }
    public void Remove(T t)
    {
        if (t == null)
        {
            throw new ArgumentNullException("t");
        }
        Context.Set<T>().Remove(t);
        Context.SaveChanges();
    }
    public IEnumerable<T> Get(Expression<Func<T, bool>> filter = null, Func<IQueryable<T>, IOrderedQueryable<T>> orderBy = null, string includeProperties = "")
    {
        IQueryable<T> query = Context.Set<T>();

        if (filter != null)
        {
            query = query.Where(filter.Expand());
        }

        foreach (var includeProperty in includeProperties.Split
            (new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries))
        {
            query = query.Include(includeProperty);
        }

        if (orderBy != null)
        {
            return orderBy(query).ToList();
        }
        else
        {
            return query.ToList();
        }
    }
    private string GetEntityName<TEntity>() where TEntity : class
    {
        return string.Format("{0}.{1}", ((IObjectContextAdapter)Context).ObjectContext.DefaultContainerName, _pluralizer.Pluralize(typeof(TEntity).Name));

    }

    public virtual IEnumerable<T> GetByBusinessKey(T entity)
    {
        return null;
    }
}    

对于任何其他表,只需创建模型类和仓库,然后继承基类即可。

使用代码:

 var context = new BabySitterContext();
 var  _commentRepository = new CommentRepository(context);
 var comment = _commentRepository.Get(x => x.PostId == id).FirstOrDefault();

0

不是,但可以这样做

Public String Get_Filed_By_Id(string table_Name,String Field_Name,string PK_val)
{
    string strRes="";
    using(mydbcontext db=new mydbcontext())
    {
      var x=db.table_Name.Where(p=>p.Id=PK_val).Select(b=>b.Field_Name).FirstOrDefault();
      strRes=Convert.Tostring(x);
    }
 return strRes;
}

不会起作用,我正在尝试将“Table_Name”和“Field_value”作为“参数”传递。 - A_Sk
然后使用查询,例如db.database.ExecuteSQLQuery或类似的函数,它将字符串(查询)作为参数。 - Lali
我相信这种方式是可能的,但我猜它会很笼统,但我想看看这种方法。 - A_Sk

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接