需要帮助理解实体框架

Tim*_*Tim 0 c# entity-framework entity-framework-6

我的前任为 HR 编写了一个 Web 应用程序,用于从 HRMS 的 401k 贡献中提取数据。事实证明,他的报告仅在捐款金额为精确金额而不是百分比时才提取追加捐款。他使用实体框架来做到这一点。我是脚本编写者,不是程序员。我知道阿多。我不知道实体框架。

数据库有一个名为 的列EARNED。追赶贡献金额获取代码 D03。追赶贡献百分比获取代码 D03B。该列还有其他几个可能的值:D04、D31、E40 等。不知何故,他的报告仅提取 D03 行。它还需要拉动 D03B 行。

如果我写 SQL,它会是这样的

SELECT * 
FROM [SageHRMS_900].[dbo].[UPCHKD] 
WHERE [EARNDED] = 'D03B' 
   OR [EARNDED] = 'D03'
Run Code Online (Sandbox Code Playgroud)

显然实体框架不使用类似的东西。相反,我看到的只是这样的东西

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;
}
Run Code Online (Sandbox Code Playgroud)

我看到 TRP_Con 类的定义位置

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; }
}
Run Code Online (Sandbox Code Playgroud)

我没有看到代码如何知道将选择限制为仅 D03 类型的贡献。


编辑:添加 hrmsEntity 类

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; }
}
Run Code Online (Sandbox Code Playgroud)

UPCHKD是900数据库中的一个表。

@Dai 评论:“另外,请(为了每个人的理智)请使用 IDE 的重构重命名功能将 hrmsEntity 重命名为 HrmsDbContext”是的...我不是程序员。:) 我编写 VBA 或 PowerShell 脚本。调整 C# 几乎是我能力的极限。

Ste*_* Py 5

第一步是查看此 TRP_ConDetail 映射到的位置/内容,因为该名称中没有任何内容与 UPCHKD 表相关。由于实体类中除了 之外没有任何属性[Key],因此要检查的两个位置将在 DbContext 本身 (hrmsEntity) 中查找该OnModelCreating()方法,或者在类型的解决方案中查找一个类EntityTypeConfiguration<TRP_ConDetail>,该类将指示数据库中的哪个表或视图该实体被映射到。这还将显示指向已为该类重命名的“Earned”列的所有属性。

鉴于您提到他的代码仅提取“D03”值,我的直觉是 TRP_ConDetail 是一个视图,因为您粘贴的代码中没有过滤代码逻辑。该代码将实体映射到表或视图并输出整个集合。数据库中可能有一个名为 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();
Run Code Online (Sandbox Code Playgroud)

这本来可以安全且轻松地更新为:

var detail = hrms.TRP_ConDetail
    .Where(x => x.Earned == "D03" || x.Earned == "D03B")
    .ToList();
Run Code Online (Sandbox Code Playgroud)

不幸的是,它看起来并不是这样实现的,了解为什么不这样做会很有趣,以及 EF 是否实际上被用作 ADO.Net 的替代品。

您应该与您的雇主讨论引入熟悉实体框架的开发人员来仔细查看实现,以确认是否使用了视图并识别可能更新底层视图或“修复”它的任何风险,以便选择标准由 EF 完成,而不是在视图定义中完成。(这将对引用视图的所有地方进行审查、修改和测试)