使用泛型函数查询EF5中的DBSet

使用泛型函数查询EF5中的DBSet

问题描述:

我看到了DbSet的各种实现,但我不确定它们是我正在寻找的。使用泛型函数查询EF5中的DBSet

基本上我们有一堆通过EF5 Code First方法设置的DbSet。我有一个编写代码的任务,根据我们在数据库中已有的记录来检查进入API的任何更新/帖子,以确保它们只有在新记录时才更新/张贴。

显然我不想为每个这些DBSet编写相同的代码,我想编写一个类/函数,它将能够将DbSet作为参数/参数,然后检查DBSet作为记录。它必须是动态的,因为它是依赖于最终用户和他们在做什么哪个DbSet将需要查询...

因此,例如,我想要做的事,如呼叫:

CheckDbUniqueRecord(Contracts)其中合同是从表单传入的合同模型的DbSet。

所以在这个模型中,我们有public class Contract

,并在MainDbContext我们有多个DbSet的其中之一是public DbSet<Contract> Contracts {get; set;}

我希望能够运行相同的代码来检查任何重复记录的DbSets我们通过简单地传递从该特定的控制器返回的类/模型与该一行功能...

我知道有一种方法来实现这一点,但我不断收到错误消息/类型来自C#的错误表明类型不匹配,等等......

任何帮助将不胜感激。

更新:我只会需要此检查数据库中的重复记录,而不是更新。在调用Put函数之前,我将处理客户端的检查更新。

我有下面的代码这是非常近的工作:

public interface getId 
     { 
      int Id { get; set; } 
     } 
     public class Check : getId 
     { 
      public int Id { get; set; } 

      public static bool CheckDBUniqueRecord<T>(T entity) where T : class, getId 
      { 
       MainDbContext db = new MainDbContext(Utility.PortalConnectionString()); 

       var myDbSet = db.Set<T>().ToList(); 

       foreach (var d in myDbSet) 
       { 
        d.Id = 0; 
        if (d == entity) return true; 

       } 
       return false; 


      } 
     } 

通过使用通用约束,但是我得到的方法调用的错误:类型XXXX不能用作类型参数“T '在通用方法yyyyyy。没有从xxxx到yyyy的隐式引用转换。

这是什么修复?

+0

所以,换句话说,你想要一个通用的方法来检查一个任意的实体在数据库中的存在,对不对?你如何期待检查完成?你想如何确定哪些字段将被包含在比较中?成员的属性?除ID之外的所有字段? – DarkSquirrel42

+0

您需要使用泛型方法来启动,然后在其中使用typeof(T),其中T是类,然后将每种类型抽象为具体方法,或者您可以使用反射T来尝试获取对象属性和使用它来执行保存更新等,您仍然需要将一些东西传递给泛型方法以确定需要创建哪种类型的CRUD。您可以从简单的单一主键对象开始,然后当确信这个工作时,为更复杂的类型编写重载方法。 – bilpor

+0

是的,实体将始终存在于数据库中,所以这不是一个问题。该检查将针对所有字段运行......基本上,我会遍历数据库记录中的每个字段,并检查传入的模型的值。如果所有字段相同,则后/更新将不会运行。发现任何已更改的字段后,它将跳出循环并运行发布/更新。我实际上只是需要它的职位,因为我会在运行更新之前检查客户端的更新。所以基本上只是为了确保数据库中没有重复的记录。 – MattE

第一件事,第一:这一切只是写下来的和未经考验......

的第一件事情很简单:你的函数签名......

public static bool CheckDbUniqueRecord<T>(T entity) 

或类似像extensionmethod东西。 ..

public static bool CheckDbUniqueRecord<T>(this DbContext db, T entity) 

基本上你想要做的就是查询您的DbContext为对应于你的实体的DbSet ...

var myDbSet = db.Set<T>(); 

现在你需要某种逻辑来找出你想检查哪些属性......这可以通过在你的实体类成员上放置属性来完成......这可以通过检查所有不是主键字段的东西来完成......你必须想出一些东西来告诉你测试哪些东西......为了简单起见,我将简单地介绍一些非常简单的事情,对于每个属性都有一个没有被命名为“ID”的getter ......根据您的实现,您最有可能想要将这些代码移动到初始化代码块不会每次都运行...

var t = typeof(T); 
var pInfos = t.GetProperties(BindingFlags.Public|BindingFlags.Instance).Where(x=>x.Name!="ID" && x.CanRead).ToArray(); 
Expression exp=null; 
Expression pT = Expression.Parameter(t); 
foreach(var p in pInfos) 
{ 
Expression m = Expression.Property(pT,p); 
Expression c = Expression.Constant(p.GetValue(entity)); 
if(tmp==null) 
{ 
tmp=Expression.Equal(m,c); 
} 
else 
{ 
tmp=Expression.AndAlso(tmp,Expression.Equal(m,c)); 
} 
} 
var myLambda=Expression.Lambda<Func<T,bool>>(tmp,pT); 


return myDbSet.AsQueryable().Any(myLambda); 
+0

我在想因为我会知道标识符I会搜索DB的MemberId,我会得到记录,然后我会遍历每个记录中的每一列,并将其与 – MattE

+0

记录中的列进行比较为什么你想实现所有与你的memberid匹配的实体?如果你想知道这样的记录是否存在,请询问DBMS ....你想知道什么会导致类似SELECT count(*)> 0 FROM ... WHERE Property1 ='Value1'AND Property2 ='Value2 '... – DarkSquirrel42