如何使用反射或泛型标准化通用实体框架C#代码?
我有三个数据库表,它们表示常用名称字符串的比较分数。它们被分成单独的表格,以加快扫描时间。它们都有相同的四列基本结构:一个ID、两个字符串和表示字符串差异的分数 数据库通过实体框架访问。在实现代码中,这使我拥有三个几乎相同的函数,每种对象类型一个:如何使用反射或泛型标准化通用实体框架C#代码?,c#,entity-framework,generics,reflection,C#,Entity Framework,Generics,Reflection,我有三个数据库表,它们表示常用名称字符串的比较分数。它们被分成单独的表格,以加快扫描时间。它们都有相同的四列基本结构:一个ID、两个字符串和表示字符串差异的分数 数据库通过实体框架访问。在实现代码中,这使我拥有三个几乎相同的函数,每种对象类型一个: private bool CheckSurnameJw(string string1, string string2, double threshold) { JwDistanceSurname jw = _rep.G
private bool CheckSurnameJw(string string1, string string2, double threshold)
{
JwDistanceSurname jw = _rep.GetJwDistanceSurname(string1, string2);
if (jw == null)
{
double dist = JaroWinklerProximity(string1, string2);
JwDistanceSurname newJw = new JwDistanceSurname { Surname1 = string1, Surname2 = string2, JwScore = dist };
_rep.Update(newJw);
_rep.SaveChanges();
return dist >= surnameProximityThreshold;
}
else
{
return jw.JwScore >= threshold;
}
}
从这个角度看,虽然我可以稍微捏一捏,但我看不出有任何明显的地方可以通过将代码输出到另一个函数来合理地改进该函数。但是,为了处理三种不同的身份类型,我不得不三次重新实现同一个逻辑块,这让我非常恼火
我将所有三个类包装在一个指定四列的接口中,看看这是否能帮助我整理东西。但事实并非如此:我不能使用通用的“get”函数,因为每个函数都在查询不同的表,同样,当我创建类的新实例时,我需要为它提供适当的类型
有没有办法使用反射/泛型来改进这一点 如果你的四个专栏都有相同的专栏名称,我肯定会选择其他类型的文章 但是,如果这四列没有共同的含义,我会使用一个接口 每种方法的表格 如果四列通常表示相同的内容,并且您认为您的表是这种常见内容的特殊类型,请使用此选项:
abstract class Common
{
public string String1 {get; set;}
public string string2 {get; set;}
public double Threshold {get; set;}
}
class Table1 : Common
{
public int Id {get; set;}
...
}
class Table2 : Common
{
public int Id {get; set;}
...
}
您的DbContext将类似于:
class MyDbContext : DbContext
{
public DbSet<Table1> Table1s {get; set;}
public DbSet<Table2> Table2s {get; set;}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<Table1>().ToTable("Table1s");
modelBuilder.Entity<Table2>().ToTable("Table2s");
}
}
用法:
IEnumerable<Table1> myTableCollection = myDbContext.Table1s
.Where(table => table...)
foreach (Table1 table1 in myTableCollection)
{
bool surNameOk = table1.CheckSurName();
Process(surNameOk);
}
这还将导致每个类型有一个表,每个表包含所有公共属性。扩展功能将类似。唯一的区别是,您没有对检索表上的姓氏执行检查,而是对检索表的公用名执行检查:
IEnumerable<Table1> retrievedTables = ...
foreach (Table1 table in retrievedTables)
{
bool SurnameOk = table1.Common.CheckSurName();
...
}
扩展功能几乎相同:
public static bool CheckSurName(this ISurnameCheckable surnameCheckable)
{
JwDistanceSurname jw = _rep.GetJwDistanceSurname(
surnameCheckable.String1, surnameCheckable.String2);
...
}
你考虑过某种干涉吗?你能发布另一个几乎相同的代码吗?只看到一个函数而不看到其他函数来比较它们的公共代码有点难重构。您是否尝试通过调用_dbcontext.Set()来创建一个以dbcontext子集为目标的repo?IEntity将是一种通用类型,实现指定3个表的公共字段的接口。这样行吗
private bool checknamesjw(字符串string1、字符串string2、双阈值),其中T:new()
?用T
替换jwdistancenamel
,对于newJw
,var newJw=newt{names1=string1,names2=string2,JwScore=dist}代码>用法类似于检查JW(“测试”,“测试”,2)代码>
IEnumerable<Table1> retrievedTables = ...
foreach (Table1 table in retrievedTables)
{
bool SurnameOk = table1.Common.CheckSurName();
...
}
interface ISurnameCheckable
{
public string String1 {get;}
public string String2 {get;}
public double Threshold {get;}
}
class Table1 : ISurnameCheckable
{
public int Id {get; set;}
public string Street {get; set;}
public string City {get; set}
// implementation of ISurnameCheckable
public string String1 {get{return this.Street;}}
public string String2 {get{return this.City;}}
...
}
public static bool CheckSurName(this ISurnameCheckable surnameCheckable)
{
JwDistanceSurname jw = _rep.GetJwDistanceSurname(
surnameCheckable.String1, surnameCheckable.String2);
...
}