需要帮助理解 Entity Framework
Need help understanding Entity Framework
我的前任为 HR 编写了一个 Web 应用程序,用于从我们的 HRMS 中提取有关 401k 贡献的数据。事实证明,他的报告仅在金额为确切金额而不是百分比时才提取追加捐款。他使用 Entity Framework 来做到这一点。我是脚本编写者,不是程序员。我知道 ADO。我不知道 Entity Framework。
数据库有一个名为 EARNED
的列。 Catch Up Contribution Amounts 获得代码 D03。 Catch Up Contribution Percentage 获得代码 D03B。该列还有其他几个可能的值:D04、D31、E40 等。不知何故,他的报告只提取了 D03 行。它还需要拉 D03B 行。
如果我写 SQL,它会像
SELECT *
FROM [SageHRMS_900].[dbo].[UPCHKD]
WHERE [EARNDED] = 'D03B'
OR [EARNDED] = 'D03'
显然 Entity Framework 不使用类似的东西。相反,我看到的只是这样的东西
hrmsEntity hrms = new hrmsEntity(dbConnection);
var detail = hrms.TRP_ConDetail.ToList();
foreach (var line in hrms.TRP_ConDetail.ToList())
{
fileData += line.Plan + line.RecordID + line.Date + line.SSN + line.Fund + line.LoanNum +
line.Amount + line.Salary + line.SalaryType + line.ContType + line.StateTax +
line.LoanPayType + line.Filler01 + Environment.NewLine;
}
我看到了 TRP_Con class 的定义
public class TRP_ConDetail
{
[Key]
public Guid ID { get; set; }
public string Plan { get; set; }
public string RecordID { get; set; }
public string Date { get; set; }
public string Name { get; set; }
public string SSN { get; set; }
public string Fund { get; set; }
public string Desc { get; set; }
public string LoanNum { get; set; }
public string Amount { get; set; }
public decimal Dollars { get; set; }
public string Salary { get; set; }
public string SalaryType { get; set; }
public string ContType { get; set; }
public string StateTax { get; set; }
public string LoanPayType { get; set; }
public string Filler01 { get; set; }
public int? LineSq { get; set; }
}
我看不到的是代码如何知道将选择限制为仅 D03 类型的贡献。
编辑:
添加 hrmsEntity class
public partial class hrmsEntity : DbContext
{
//public hrmsEntity()
// : base("name=hrmsEntityModelDSM")
//{
//}
/*Base entity connection depends on the entity of the company*/
public hrmsEntity(string dbConnection) : base($"name={dbConnection}") { }
//public hrmsEntity(string connectionString) : base(connectionString) { }
public virtual DbSet<TRP_ConSourceTotal> TRP_ConSourceTotal { get; set; }
public virtual DbSet<TRP_ConDetail> TRP_ConDetail { get; set; }
public virtual DbSet<TRP_MaintFile> TRP_MaintFile { get; set; }
}
UPCHKD 是 900 数据库中的 table。
@Dai 评论:“另外,请(为了每个人的理智)请使用您的 IDE 的重构重命名功能将 hrmsEntity 重命名为 HrmsDbContext”
是的...我不是程序员。 :) 我编写 VBA 或 PowerShell 脚本。调整 C# 几乎是我能力的极限。
第一步是查看此 TRP_ConDetail 映射到的 where/what,因为该名称中没有任何内容与 UPCHKD table 相关。由于实体 class 中除了 [Key]
之外没有其他属性,因此要检查的两个地方将在 OnModelCreating()
方法的 DbContext 本身 (hrmsEntity) 中,或者查找 class 在类型 EntityTypeConfiguration<TRP_ConDetail>
的解决方案中,这将指示该实体映射到数据库中的哪个 Table 或视图。这还将显示指向已为 class.
重命名的“Earned”列的任何属性
鉴于您提到他的代码仅提取“D03”值,我的直觉是 TRP_ConDetail 是一个视图,因为您粘贴的代码中没有过滤代码逻辑。该代码将实体映射到 table 或视图并输出整个集合。数据库中可能有一个名为 TRP_ConDetail 的视图,您可以在其中找到类似 WHERE UPCHKD.EARNED = 'D03'
的内容,您可以将其扩展为包含“D03B”值。
但是,请记住,如果这就是系统的实施方式,这是一个警告,这将是一个非常糟糕的设计,因为如果您进行更改,它将影响所有地方 这个 TRP_ConDetail DbSet
被引用了。任何其他只期望 D03 的代码现在会同时收到 D03 和 D03B,因此这很可能会在系统的其他区域引入错误。应避免在底层视图中使用过滤规则,除非正是出于这个原因,它是非常核心级别的全局应用规则。通常您希望看到的是在 Linq 表达式中完成的过滤:
例如,如果视图简单地组合了这个 UPCHKD 和一些相关数据,其中像“Earned”这样的字段是视图的一部分,那么代码该区域中的 Linq 查询看起来更像:
var detail = hrms.TRP_ConDetail
.Where(x => x.Earned == "D03")
.ToList();
哪个安全且易于更新到:
var detail = hrms.TRP_ConDetail
.Where(x => x.Earned == "D03" || x.Earned == "D03B")
.ToList();
不幸的是,它看起来不像是以这种方式实现的,很有趣的是看看为什么不这样做,以及 EF 是否真的被用来代替 ADO.Net。
您应该与您的雇主商量,让其聘请熟悉 Entity Framework 的开发人员来仔细查看实施情况,以确认是否使用了视图并识别可能更新基础视图的任何风险,或者“修复”它以便选择标准由 EF 而不是在视图定义中完成。 (这将对审查、修改和测试引用该视图的任何地方产生影响)
我的前任为 HR 编写了一个 Web 应用程序,用于从我们的 HRMS 中提取有关 401k 贡献的数据。事实证明,他的报告仅在金额为确切金额而不是百分比时才提取追加捐款。他使用 Entity Framework 来做到这一点。我是脚本编写者,不是程序员。我知道 ADO。我不知道 Entity Framework。
数据库有一个名为 EARNED
的列。 Catch Up Contribution Amounts 获得代码 D03。 Catch Up Contribution Percentage 获得代码 D03B。该列还有其他几个可能的值:D04、D31、E40 等。不知何故,他的报告只提取了 D03 行。它还需要拉 D03B 行。
如果我写 SQL,它会像
SELECT *
FROM [SageHRMS_900].[dbo].[UPCHKD]
WHERE [EARNDED] = 'D03B'
OR [EARNDED] = 'D03'
显然 Entity Framework 不使用类似的东西。相反,我看到的只是这样的东西
hrmsEntity hrms = new hrmsEntity(dbConnection);
var detail = hrms.TRP_ConDetail.ToList();
foreach (var line in hrms.TRP_ConDetail.ToList())
{
fileData += line.Plan + line.RecordID + line.Date + line.SSN + line.Fund + line.LoanNum +
line.Amount + line.Salary + line.SalaryType + line.ContType + line.StateTax +
line.LoanPayType + line.Filler01 + Environment.NewLine;
}
我看到了 TRP_Con class 的定义
public class TRP_ConDetail
{
[Key]
public Guid ID { get; set; }
public string Plan { get; set; }
public string RecordID { get; set; }
public string Date { get; set; }
public string Name { get; set; }
public string SSN { get; set; }
public string Fund { get; set; }
public string Desc { get; set; }
public string LoanNum { get; set; }
public string Amount { get; set; }
public decimal Dollars { get; set; }
public string Salary { get; set; }
public string SalaryType { get; set; }
public string ContType { get; set; }
public string StateTax { get; set; }
public string LoanPayType { get; set; }
public string Filler01 { get; set; }
public int? LineSq { get; set; }
}
我看不到的是代码如何知道将选择限制为仅 D03 类型的贡献。
编辑: 添加 hrmsEntity class
public partial class hrmsEntity : DbContext
{
//public hrmsEntity()
// : base("name=hrmsEntityModelDSM")
//{
//}
/*Base entity connection depends on the entity of the company*/
public hrmsEntity(string dbConnection) : base($"name={dbConnection}") { }
//public hrmsEntity(string connectionString) : base(connectionString) { }
public virtual DbSet<TRP_ConSourceTotal> TRP_ConSourceTotal { get; set; }
public virtual DbSet<TRP_ConDetail> TRP_ConDetail { get; set; }
public virtual DbSet<TRP_MaintFile> TRP_MaintFile { get; set; }
}
UPCHKD 是 900 数据库中的 table。
@Dai 评论:“另外,请(为了每个人的理智)请使用您的 IDE 的重构重命名功能将 hrmsEntity 重命名为 HrmsDbContext” 是的...我不是程序员。 :) 我编写 VBA 或 PowerShell 脚本。调整 C# 几乎是我能力的极限。
第一步是查看此 TRP_ConDetail 映射到的 where/what,因为该名称中没有任何内容与 UPCHKD table 相关。由于实体 class 中除了 [Key]
之外没有其他属性,因此要检查的两个地方将在 OnModelCreating()
方法的 DbContext 本身 (hrmsEntity) 中,或者查找 class 在类型 EntityTypeConfiguration<TRP_ConDetail>
的解决方案中,这将指示该实体映射到数据库中的哪个 Table 或视图。这还将显示指向已为 class.
鉴于您提到他的代码仅提取“D03”值,我的直觉是 TRP_ConDetail 是一个视图,因为您粘贴的代码中没有过滤代码逻辑。该代码将实体映射到 table 或视图并输出整个集合。数据库中可能有一个名为 TRP_ConDetail 的视图,您可以在其中找到类似 WHERE UPCHKD.EARNED = 'D03'
的内容,您可以将其扩展为包含“D03B”值。
但是,请记住,如果这就是系统的实施方式,这是一个警告,这将是一个非常糟糕的设计,因为如果您进行更改,它将影响所有地方 这个 TRP_ConDetail DbSet
被引用了。任何其他只期望 D03 的代码现在会同时收到 D03 和 D03B,因此这很可能会在系统的其他区域引入错误。应避免在底层视图中使用过滤规则,除非正是出于这个原因,它是非常核心级别的全局应用规则。通常您希望看到的是在 Linq 表达式中完成的过滤:
例如,如果视图简单地组合了这个 UPCHKD 和一些相关数据,其中像“Earned”这样的字段是视图的一部分,那么代码该区域中的 Linq 查询看起来更像:
var detail = hrms.TRP_ConDetail
.Where(x => x.Earned == "D03")
.ToList();
哪个安全且易于更新到:
var detail = hrms.TRP_ConDetail
.Where(x => x.Earned == "D03" || x.Earned == "D03B")
.ToList();
不幸的是,它看起来不像是以这种方式实现的,很有趣的是看看为什么不这样做,以及 EF 是否真的被用来代替 ADO.Net。
您应该与您的雇主商量,让其聘请熟悉 Entity Framework 的开发人员来仔细查看实施情况,以确认是否使用了视图并识别可能更新基础视图的任何风险,或者“修复”它以便选择标准由 EF 而不是在视图定义中完成。 (这将对审查、修改和测试引用该视图的任何地方产生影响)