带有 ODP.Net Oracle.ManagedDataAccess 的 EF 6,如何对 Class 属性使用非大写字母?

EF 6 with ODP.Net Oracle.ManagedDataAccess, How to Use Non-Capital Letter for Class Properties?

我将 EF 6 与 ODP.Net Oracle.ManagedDataAccess 一起用于我的 ASP.Net MVC Web 应用程序。

我有以下名为 EmployeeModel(在 Model\Employee.cs 文件中):

[Table("TBLEMPLOYEE")]
public class Employee {
    public int Id { get; set; }
    public string Name { get; set; }
    public string Gender { get; set; }
    public DateTime DateOfBirth { get; set; }
    public int EmployeeType { get; set; }
    public double? AnnualSalary { get; set; }
    public double? HourlyPay { get; set; }
    public double? HoursWorked { get; set; }
    public string City { get; set; }
}

以及EmployeeContext.cs

public class EmployeeContext : DbContext {
    public DbSet<Employee> Employees { get; set; }
    protected override void OnModelCreating(DbModelBuilder modelBuilder) {
        modelBuilder.HasDefaultSchema("myschema");
    }
}

然后,在我的 EmployeeController.cs 中,我像这样使用 EmployeeEmployeeContext

public ActionResult Details(int id = 1) {
    try {
        EmployeeContext employeeContext = new EmployeeContext();
        employeeContext.Database.Log = s => System.Diagnostics.Debug.WriteLine(s);
        Employee employee = employeeContext.Employees.Single(x => x.ID == id);
        return View(employee);
    } catch (Exception e) {
        return View(e);
    }
}

当我收到以下内部异常错误时:

Oracle.ManagedDataAccess.Client.OracleException: ORA-00904: "Extent1"."Id": invalid identifier

异常错误发生在:

Employee employee = employeeContext.Employees.Single(x => x.ID == id);

当我使用调试输出控制台进一步调试时,我注意到 EF 生成以下 SQL 查询来获取数据:

SELECT 
"Extent1"."Id" AS "Id", 
"Extent1"."Name" AS "Name", 
"Extent1"."Gender" AS "Gender", 
"Extent1"."DateOfBirth" AS "DateOfBirth", 
"Extent1"."EmployeeType" AS "EmployeeType", 
"Extent1"."AnnualSalary" AS "AnnualSalary", 
"Extent1"."HourlyPay" AS "HourlyPay", 
"Extent1"."HoursWorked" AS "HoursWorked", 
"Extent1"."City" AS "City"
FROM "MYSCHEMA"."TBLEMPLOYEE" "Extent1"
WHERE ("Extent1"."Id" = :p__linq__0) AND (ROWNUM <= (2) )

随着我进行更多研究,我了解到由于 SQL 查询列名称中存在引号 " "(例如 ."Id"".EmployeeType"".HourlyPay"等),查询找不到匹配的列名,因为Oracle数据Table列名全部用大写字母表示(即:."ID"".EMPLOYEETYPE"".HOURLYPAY" 等等)。

现在,当我将 class 定义更改为如下内容时:

[Table("TBLEMPLOYEE")]
public class Employee {
    public int ID { get; set; }
    public string NAME { get; set; }
    public string GENDER { get; set; }
    public DateTime DATEOFBIRTH { get; set; }
    public int EMPLOYEETYPE { get; set; }
    public double? ANNUALSALARY { get; set; }
    public double? HOURLYPAY { get; set; }
    public double? HOURSWORKED { get; set; }
    public string CITY { get; set; }
}

它工作得很好。 但我不想要那个

作为一名典型的 C# 编码员,我发现 非常不寻常 class fields/properties.

的所有字母都大写

我的问题是,是否有任何方法可以保留使用大写字母和小写字母组合的 class 属性,仅用于查询,生成这些属性的大写字母版本?

同样,如果这些事情很重要,我会使用 EF 6.0.0.0 和 ODP.Net Oracle.ManagedDataAccess 版本 4.121.2.0Oracle.ManagedDataAccess.EntityFramework 版本 6.121.2.0

您可以在每个 属性 上使用 Column 数据属性来指定在创建 table 时要使用的映射列名称,与 Table 属性。然后,您的实际 属性 名称可以正确格式化:

[Table("TBLEMPLOYEE")]
public class Employee {
    [Column("ID")]
    public int Id { get; set; }

    [Column("NAME")]
    public string Name { get; set; }

    etc...
}

更多信息:https://msdn.microsoft.com/en-us/data/jj591583.aspx#TableColumn

您还可以在 DbContext 中使用流畅的 API 来指定列名映射:

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
    //Configure Column
    modelBuilder.Entity<Employee>()
                .Property(p => p.Id)
                .HasColumnName("ID");

    modelBuilder.Entity<Employee>()
                .Property(p => p.Name)
                .HasColumnName("NAME");
}

参考:http://www.entityframeworktutorial.net/code-first/configure-property-mappings-using-fluent-api.aspx

一种更自动化(更简单)的方法是利用 EF Custom Code First Conventions 功能。

首先你需要一个像这样的简单class

using System.Data.Entity.ModelConfiguration.Conventions;
using System.Data.Entity.Core.Metadata.Edm;

public class UppercaseColumnNameConvention : IStoreModelConvention<EdmProperty>
{
    public void Apply(EdmProperty item, DbModel model)
    {
        item.Name = item.Name.ToUpper();
    }
}

然后在您的上下文中 class

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
    modelBuilder.Conventions.Add<UppercaseColumnNameConvention>();
    // ...
}

大功告成。