简体   繁体   English

Linq to实体-动态查询

[英]Linq to entity - dynamic query

public void ApproveRowTable(string tablename, List<int> idValues)
{
    foreach (var x in idValues)
    {
            var context = new SSPModel.sspEntities();
            var genRules = (from a in context.GeneralRules
                            where a.ID == x 
                            select a).SingleOrDefault();
            genRules.Approved_by = GlobalClass.GlobalVar;
            genRules.Approved_on = DateTime.Now;
            context.SaveChanges();
    }
}

In my query ( from a in context.GeneralRules ...) I would like to make it query base on a parameter (tablename) rather than i have to go and supply the name of the table in the query (as it is doing right now.). 在我的查询中( from a in context.GeneralRules ...),我想使它基于参数(表名)进行查询,而不是我必须在查询中提供表的名称(因为它做得正确)现在。)。 Any way i can get it to do that .. basic.. from a in context.TABLENAME -- TABLENAME is a parameter that is going to be passed when the function is called. 我可以通过任何方式从in context.TABLENAME -- TABLENAME获取它的基本context.TABLENAME -- TABLENAME是一个将在调用函数时传递的参数。 Help 救命

This will be difficult if your entity types do not all implement the same interface or derive from the same class. 如果您的实体类型不都实现相同的接口或不从同一个类派生,则这将很困难。 If they do, it's pretty simple: 如果他们这样做,那就很简单了:

// example base type, which your entities would need to implement
public interface IApprovable
{
    public int ID {get; set;}
    public string Approved_by {get; set;}
    public DateTime Approved_on {get; set;}
}
//...
public void ApproveRowTable<T>(List<int> idValues)
    where T : IApprovable
{
    using(var context = new SSPModel.sspEntities())
    {
        var table = context.Set<T>();
        var entities = table.Where(e => idValues.Contains(e.ID));
        foreach(var entity in entities)
        {
            entity.Approved_by = GlobalClass.GlobalVar;
            entity.Approved_on = DateTime.Now;  
        }
        context.SaveChanges();  
    }
}

If your entity types do not implement a common base type, then you should modify them by creating empty partials which do implement it: 如果您的实体类型未实现通用基本类型,则应通过创建实现它的空部分来修改它们:

public partial class GeneralRule : IApprovable {}

If you cannot do that, then you can do something like the following. 如果您不能这样做,则可以执行以下操作。 (I'm assuming ID is the PK, so we can use Find() rather than needing to build an expression: (我假设ID是PK,因此我们可以使用Find()而不需要构建表达式:

public void ApproveTableRows(Type entityType, IEnumerable<int> idsToApprove)
{
    using(var context = new SSPModel.sspEntities())
    {
        var set = context.Set(entityType);
        if(set == null)
            throw new ArgumentException("No DbSet found with provided name", "tableSetName");

        var approveByProperty = entityType.GetProperty("Approved_by");
        var approveOnProperty = entityType.GetProperty("Approved_on");
        if(approveByProperty == null || approveOnProperty == null)
            throw new InvalidOperationException("Entity type does not contain approval properties");

        foreach (object id in idsToApprove)
        {
            var entityInstance = set.Find(id);
            approveByProperty.SetValue(entityInstance, GlobalClass.GlobalVar);
            approveOnProperty.SetValue(entityInstance, DateTime.Now);
        }

        context.SaveChanges();
    }
}

As you can see, this is less efficient, as it issues a new query for each ID rather than getting them all at once. 如您所见,这效率较低,因为它会为每个ID发出一个新查询,而不是一次获取所有ID。 Also, the method accepts an entity Type rather than a string, to avoid the need to hunt down the right property by reflection. 同样,该方法接受实体Type而不是字符串,以避免需要通过反射来查找正确的属性。 This could be improved, but really I think you should probably update your entities to implement a shared interface. 可以对此进行改进,但是实际上我认为您应该更新您的实体以实现共享接口。

I assume you would like to have the method generic. 我假设您想使用通用方法。 When you are using EF all your tables are represented as objects, so you don't have to specify which table you want by name, just use a generic parameter. 使用EF时,所有表都表示为对象,因此不必通过名称指定要使用的表,只需使用通用参数即可。

I doubt that my solution is best, but it should work. 我怀疑我的解决方案是最好的,但是它应该可以工作。 But I have to warn you, reflection is slow and many times its usage is not right. 但是我必须警告您,反射很慢,而且很多时候反射的使用是不正确的。

public void ApproveRowTable<T>(List<int> idValues)
{
    var context = new SSPModel.sspEntities();
    var table = context.GetType().GetProperties().OfType<T>().Single();
    var genRules = (from a in table
                            where a.ID == x 
                            select a).SingleOrDefault();
            genRules.Approved_by = GlobalClass.GlobalVar;
            genRules.Approved_on = DateTime.Now;
            context.SaveChanges();
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM