问题
I am using the EF 6 with ODP.Net Oracle.ManagedDataAccess
for my ASP.Net MVC Web application.
I have the following Model
called Employee
(in Model\Employee.cs
file):
[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; }
}
As well as EmployeeContext.cs
public class EmployeeContext : DbContext {
public DbSet<Employee> Employees { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder) {
modelBuilder.HasDefaultSchema("myschema");
}
}
Then, in my EmployeeController.cs
, I use the Employee
and the EmployeeContext
like this:
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);
}
}
When I get the following Inner exception error:
Oracle.ManagedDataAccess.Client.OracleException: ORA-00904: "Extent1"."Id": invalid identifier
The exception error occurs in:
Employee employee = employeeContext.Employees.Single(x => x.ID == id);
As I debug further by using my Debug output console, I noticed that the EF generates the following SQL query to fetch the data:
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) )
And as I do some more research, I understand that due to the present of the quotation marks " "
in the SQL query column names (such as ."Id"
, ".EmployeeType"
, ".HourlyPay"
and so on), the query cannot find matching Column names as the Oracle Data Table column name is all represented in capital letters (that is: ."ID"
, ".EMPLOYEETYPE"
, ".HOURLYPAY"
and so on).
Now, when I changed the class definition into something like this:
[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; }
}
It works perfectly fine. But I do not want that.
As a typical C# coder, I found it quite unusual to have all capital letters for class fields/properties.
My question is, is there any way to retain the class properties using combination of capital and small letters yet, only for querying, generated capitalized letters version of those properties?
Again, I use EF 6.0.0.0
and ODP.Net Oracle.ManagedDataAccess
version 4.121.2.0
and Oracle.ManagedDataAccess.EntityFramework
version 6.121.2.0
if those things matter.
回答1:
You can use the Column
data attribute on each property to specify the mapped column name to use when the table is created, much the same as the Table
attribute. Then, your actual property names can be correctly formatted:
[Table("TBLEMPLOYEE")]
public class Employee {
[Column("ID")]
public int Id { get; set; }
[Column("NAME")]
public string Name { get; set; }
etc...
}
More info: https://msdn.microsoft.com/en-us/data/jj591583.aspx#TableColumn
You can also use the fluent API in your DbContext
to specify a column name mapping:
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");
}
Reference: http://www.entityframeworktutorial.net/code-first/configure-property-mappings-using-fluent-api.aspx
回答2:
A more automated (easier) way would be to utilize EF Custom Code First Conventions feature.
First you'll need a simple class like this
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();
}
}
then in your context class
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Conventions.Add<UppercaseColumnNameConvention>();
// ...
}
and you are done.
来源:https://stackoverflow.com/questions/35423692/ef-6-with-odp-net-oracle-manageddataaccess-how-to-use-non-capital-letter-for-cl