使用通用函数在EF5中查询DBSet

时间:2016-12-22 14:25:37

标签: c# entity-framework generics constraints dbset

我已经看过DbSet的各种实现,但我不确定它们是我正在寻找的。

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

显然,我不想为每个DBSet编写相同的代码,我想写一个单独的类/函数,它可以将DbSet作为参数/参数然后检查DBSet的记录。它需要是动态的,因为它取决于最终用户以及他们正在做什么,需要查询哪个DbSet ......

所以我想做一些像call:

这样的事情

CheckDbUniqueRecord(Contracts)其中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不能用作类型参数&#39; T&#39;在通用方法yyyyyy。没有从xxxx到yyyy的隐式引用转换。

对此有何解决方法?

1 个答案:

答案 0 :(得分:0)

首先要做的是:所有这些都只是写下来并且未经测试......

首先很简单:你的功能签名......

public static bool CheckDbUniqueRecord<T>(T entity)

或类似扩展方法......

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

基本上你想要做的是查询你的DbContext以获得与你的实体相对应的DbSet ......

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

现在你需要某种逻辑来找出你要检查的属性......可以通过在你的实体类成员上放置属性来完成......这可以通过检查不是主要的所有内容来完成关键领域......你必须想出一些东西来告诉你要测试哪些东西...为了简单起见,这个答案我只是有一些非常简单的东西,每个属性都有一个吸气剂不是命名&#34; ID&#34; ...根据您的实现,您很可能希望将这些代码中的一部分移动到每次都不运行的初始化代码块中...

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);