C#: Change Retrieval DataType for Entity Framework
I'm trying to convert a project that is currently using a custom DAO framework to using Entity Framework. The system is quite large so changes to the database (a SQL Azure DB if that matters) itself aren't particularly feasible and should be avoided if possible.
The problem is with the ID column. Unfortunately when the system was created, there are some tables that have a bigint
datatype, and some that have an int
- but the models themselves all come from a base class having a long
for the ID. The previous framework was able to handle this situation, but I have been unable to find a way to do it with entity framework.
Below is the most trivial example I can think of:
public class Context : DbContext {
public IDbSet<Foo> Foos {get;set;}
public IDbSet<Bar> Bars {get;set;}
}
public abstract class BaseClass {
public long ID;
}
public class Foo : BaseClass {
...
}
public class Bar : BaseClass {
...
}
SQL Table: Foo
+-------------+
| id : bigint |
| ... |
+-------------+
SQL Table : Bar
+-------------+
| id : int |
| ... |
+-------------+
When I try to load a Bar
model, I get this error:
The 'ID' property on 'BaseClass' could not be set to a 'Int32' value. You must set this property to a non-null value of type 'Int64'.
I'd like to find a way to tell the system that Bar has ints, while Foo has longs. I've tried overriding OnModelCreating
in the context and defining HasColumnType
for Bar
. That gave me a new error:
Schema specified is not valid. Errors:
(105,12) : error 2019: Member Mapping specified is not valid. The type 'Edm.Int64[Nullable=False,DefaultValue=]' of member 'ID' in type 'Bar' is not compatible with 'SqlServer.int[Nullable=False,DefaultValue=,StoreGeneratedPattern=Identity]' of member 'ID' in type 'CodeFirstDatabaseSchema.Bar'.
It seems to me that if I could only change the expected data type for the ID
of BaseClass
to int
before sending the request to the server, then I should be able to up-convert to a long
after I receive the response. Ideally, I'd like to do this on a per-class basis.
Can anyone point me in the right direction?
While you can implicitly cast a bigint
to an int
in SQL Server, it appears that the Entity framework EDM types (which is really what you're dealing with) doesn't allow an implicit transformation from a 64-bit integer type to a 32-bit integer type.
This is probably for good reason, because you could easily overflow and have values that don't fit in the int
fields.
That said, you should have two base classes, one for an int
ID and one for a long
ID. It's not pretty, but it enforces logic that you definitely want; you won't be able to store values that are larger than what can fit into an int
in the database, so why would you want to be able to do it on the code level? The Entity framework is doing the right thing here in not letting you apply that transformation.
上一篇: 模板定义如何与模板声明相匹配?
下一篇: C#:更改实体框架的检索数据类型