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