Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/linq/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 实体框架中不同表上的抽象操作_C#_Linq_Entity Framework_Generics - Fatal编程技术网

C# 实体框架中不同表上的抽象操作

C# 实体框架中不同表上的抽象操作,c#,linq,entity-framework,generics,C#,Linq,Entity Framework,Generics,我有几个表格,例如:猫,狗,和兔子。每个表都有两个字段:整数主键XId和字符串XName,其中X是表的名称:Cat、Dog或Rabbit 然后,对于每个包含名称的表,我有一个字符串[]。我需要将表与数组同步:删除没有在数组中列出名称的表记录,并为仅在数组中存在的名称添加新记录 最简单的方法是复制代码三次,然后在所有地方将CatName更改为DogName,等等。然而,我正在寻找一个更干净的解决方案,它不会重复代码 如果它不是一个表,而是一个简单的IList,我会编写以下代码片段: void Sy

我有几个表格,例如:
,和
兔子
。每个表都有两个字段:整数主键
XId
和字符串
XName
,其中
X
是表的名称:
Cat
Dog
Rabbit

然后,对于每个包含名称的表,我有一个
字符串[]
。我需要将表与数组同步:删除没有在数组中列出名称的表记录,并为仅在数组中存在的名称添加新记录

最简单的方法是复制代码三次,然后在所有地方将
CatName
更改为
DogName
,等等。然而,我正在寻找一个更干净的解决方案,它不会重复代码

如果它不是一个表,而是一个简单的
IList
,我会编写以下代码片段:

void SyncData<T>(IList<T> source, string[] names, Func<T, string> nameGetter, Func<string, T> creator)
{
    var toRemove = source.Where(x => !names.Contains(nameGetter(x))).ToArray();
    foreach(var item in toRemove)
        source.Remove(item);

    var toCreate = names.Where(x => !source.Any(i => nameGetter(i) != x)).ToArray();
    foreach(var item in toCreate)
        source.Add(creator(item));
}

SyncData(cats, catNames, c => c.CatName, n => new Cat { CatName = n });
SyncData(dogs, dogNames, d => d.DogName, n => new Dog { DogName = n });
...
void SyncData(IList源、字符串[]名称、Func nameGetter、Func创建者)
{
var toRemove=source.Where(x=>!names.Contains(nameGetter(x))).ToArray();
foreach(toRemove中的var项目)
来源。删除(项目);
var toCreate=names.Where(x=>!source.Any(i=>nameGetter(i)!=x)).ToArray();
foreach(toCreate中的变量项)
来源.添加(创建者(项目));
}
SyncData(cats,catNames,c=>c.CatName,n=>newcat{CatName=n});
SyncData(dogs,DogName,d=>d.DogName,n=>newdog{DogName=n});
...
对于
IQueryable
,可以实现类似的功能吗?不幸的是,它不能按原样工作,因为LINQ提供程序无法将函数调用转换为SQL查询

由于字段名不同,我无法为对象创建公共接口。更改POCO类定义也不是一个选项。

在的帮助下,可以实现这一点

IQueryable
没有
Add
方法,因此我们需要使用
IDbSet
或类似的方法

你可以试试这个

public static class SyncExtension
{
    public static void SyncData<T>(
        this IDbSet<T> source, 
        string[] names, 
        Expression<Func<T, string>> name, 
        Func<string, T> creator) where T : class
    {
        var columnName = ((MemberExpression)name.Body).Member.Name;

        var removePredicate = string.Format("!{0}.Contains(@0)", columnName);
        var toRemove = source.Where(removePredicate, names).ToArray();
        foreach (var item in toRemove)
            source.Remove(item);

        var addPredicate = string.Format("{0} = @0", columnName);
        var toCreate = names.Where(x => 
            !source.Where(addPredicate, x).Any()).ToArray();
        foreach (var item in toCreate)
            source.Add(creator(item));
    }
}
公共静态类同步扩展
{
公共静态无效同步数据(
这是一组源代码,
字符串[]名称,
表达式名称,
Func creator)其中T:class
{
var columnName=((MemberExpression)name.Body).Member.name;
var removePredicate=string.Format(“!{0}.Contains(@0)”,columnName);
var toRemove=source.Where(removePredicate,names.ToArray();
foreach(toRemove中的var项目)
来源。删除(项目);
var addPredicate=string.Format(“{0}=@0”,columnName);
var toCreate=names.Where(x=>
!source.Where(addPredicate,x).Any()).ToArray();
foreach(toCreate中的变量项)
来源.添加(创建者(项目));
}
}
用法

using (var db = new AppContext())
{
    var names = new[] { "A", "B" };
    db.Set<Cat>().SyncData(names, x => x.Name, x => new Cat { Name = x });
    db.SaveChanges();
}
使用(var db=new AppContext())
{
变量名称=新[]{“A”,“B”};
db.Set().SyncData(名称,x=>x.Name,x=>newcat{Name=x});
db.SaveChanges();
}