简体   繁体   English

使用EF模型从字符串字段存储和检索枚举的无缝方法

[英]Seamless way to store and retrieve enums from a string field using EF Model

I have several enums, that represent states, and all correspond to string fields on the EF model. 我有几个代表状态的枚举,它们都对应于EF模型上的字符串字段。 All enums values are chosen so they can be easily represented as chars, so they are set like this: 选择所有枚举值,以便可以轻松地将它们表示为char,因此将它们设置如下:

public enum eStateCode
{
    Running = 'R',
    Terminated = 'T',
    Cancelled = 'C',
}

This way database field can be a char[1] type, capable of storing meaning codes, instead a abstract numeric field. 这样,数据库字段可以是char [1]类型,能够存储含义代码,而不是抽象的数字字段。 This approach works seamless using Linq to SQL, because char SQL columns are mapped to char fields, but not using EF. 该方法使用Linq to SQL无缝运行,因为char SQL列映射到char字段,但不使用EF。

Using EF, when i try to use it on a lambda expression like this 使用EF,当我尝试在这样的lambda表达式上使用它时

s => s.WFStateCode == ((char)ClassX.eStateCode.Running).ToString())

i get the 我得到了

LINQ to Entities does not recognize the method LINQ to Entities无法识别该方法

error, meaning that ((char)ClassX.eStateCode.Running).ToString() was sent to SQL. 错误,表示((char)ClassX.eStateCode.Running).ToString()已发送到SQL。

I can circumvent the problem by putting put ((char)ClassX.eStateCode.Running).ToString() in a variable but makes the code much more verbose. 我可以通过将put ((char)ClassX.eStateCode.Running).ToString()放在变量中来解决问题,但是会使代码更加冗长。 I read several posts but none say how I can force EF to resolve the part of expression on the client side. 我读了几篇文章,但没有人说我如何强迫EF在客户端解析表达式的一部分。

It is possible to define a method that can be used in a lambda expression as a literal, so it will not be sent to SQL? 可以定义一个可以在lambda表达式中用作文字的方法,因此它不会发送到SQL吗?

The error means that EntityFramework cannot translate your code into SQL. 该错误意味着EntityFramework无法将您的代码转换为SQL。 You can convert it to string before sending to EntityFramework: 您可以在将其发送到EntityFramework之前将其转换为字符串:

string stateCode = ((char)ClassX.eStateCode.Running).ToString();
.............
s => s.WFStateCode == stateCode

Update 更新资料

You can change your model and set type of WFStateCode to eStateCode . 您可以更改模型并将WFStateCode类型设置为eStateCode By doing so, you will not need any conversion. 这样,您将不需要任何转换。 EntityFramework supports enums from EF5. EntityFramework支持EF5中的枚举。 Your final code should be something like: 您的最终代码应类似于:

s => s.WFStateCode == ClassX.eStateCode.Running

It is possible to define a method that can be used in a lambda expression as a literal, so it will not be sent to SQL? 可以定义一个可以在lambda表达式中用作文字的方法,因此它不会发送到SQL吗?

No, that's not possible. 不,那不可能。

But I could suggest you another approach that would keep your current design and at the same time will allow you to use an even more concise syntax than 但是我可以建议您使用另一种方法来保留当前的设计,同时使您可以使用比以下方法更简洁的语法

s => s.WFStateCode == ((char)ClassX.eStateCode.Running).ToString())

Right after each enum declare another static class with static readonly fields containing the string codes of the enum members. 在每个enum声明另一个带有静态只读字段的静态类,该字段包含enum成员的字符串代码。 Something like this: 像这样:

public enum eStateCode
{
    Running = 'R',
    Terminated = 'T',
    Cancelled = 'C',
}

public static class DbStateCode
{
    public static readonly string Running = ((char)eStateCode.Running).ToString();
    public static readonly string Terminated = ((char)eStateCode.Terminated).ToString();
    public static readonly string Cancelled = ((char)eStateCode.Cancelled).ToString();
}

Yes, that requires some additional effort. 是的,这需要一些额外的努力。 But it's one time effort and once you have just several enums like this I think it's worth enough. 但这是一次努力,一旦您只有几个这样的枚举,我认为就足够了。 Because then you can use simply: 因为这样您可以简单地使用:

s => s.WFStateCode == ClassX.DbStateCode.Running

Unfortunately, this is one of the many shortfalls of Entity Framework. 不幸的是,这是实体框架的众多不足之一。 If your column is char(1) or nchar(1) in SQL Server, EF should be able to map it to a char property, and therefore your statement could be: 如果您的列是SQL Server中的char(1)或nchar(1),则EF 应该能够将其映射到char属性,因此您的语句可以是:

s => s.WFStateCode == (char)ClassX.eStateCode.Running

However, this is not supported. 但是,不支持此功能。 Here is a work-around: 解决方法:

Make your column an integral type. 使您的列成为整数。

alter table [YourTable] add [WFStateId] int not null default 1
update [YourTable] set [WFStateId] = case([WFStateCode])
when 'R' then 1
when 'T' then 2
else 3 end

I know this makes it more difficult to read for someone running a select on the database, but this can be alleviated by creating a new table to join to: 我知道这会使在数据库上运行select的人阅读起来更加困难,但这可以通过创建一个新表来加入来减轻:

create table [WFState](
[Id] int not null identity primary key,
[Name] nvarchar(30) not null)
insert [WFState] values
('Running'),
('Terminated'),
('Cancelled')

To keep up good database design practices, add a foreign key: 为了保持良好的数据库设计实践,请添加外键:

alter table [YourTable] add constraint [FK_YourTable_WFState] foreign key([WFStateId]) references WFState([Id])

Then you can happily change your 'WFStateCode' property to make it type ClassX.eStateCode and change your enum definition: 然后,您可以愉快地更改“ WFStateCode”属性,使其类型为ClassX.eStateCode并更改您的枚举定义:

public enum eStateCode
{
    Running = 1,
    Terminated = 2,
    Cancelled = 3,
}

Now you will be able to freely query against it like this: 现在,您可以像这样自由查询它:

s => s.WFStateCode == ClassX.eStateCode.Running

I understand this does not answer your question about mapping a string field to enum, but this workaround will improve your system in two ways: 我了解这不能回答您有关将字符串字段映射到枚举的问题,但是此解决方法将通过两种方式改善您的系统:

1: Takes away the magic string anti-pattern (What if a user doesn't know that 'R' means running, etc.) 1:取消魔术字符串反模式(如果用户不知道'R'表示正在运行,该怎么办?)

2: Adds integrity to your database. 2:将完整性添加到您的数据库。 Now no one can break your system by assigning an invalid status to your table, EG set [WFStatusCode] = 'X' 现在,没有人可以通过为表分配无效状态来破坏系统,例如EG set [WFStatusCode] = 'X'

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 使用EF5存储模型图像并在MVC视图中检索的最佳方法 - Best way to store model image using EF5 and retrieve in MVC View 如何在具有序列化字符串字段的 redis 中存储和检索 model - how to store and retrieve model in redis that has a serialized string field 从枚举中存储和读取其他信息的有效方法是什么? - What is the efficient way to store and read additional information from enums NHibernate:使用字符串映射枚举集合并将其存储为nvarchar - NHibernate: map collection of enums using string and store as nvarchar 有没有正确的方法来检索SQL中的字符串字段 - Is there a right way to retrieve a String field in SQL 使用列的字符串表示检索/更新EF实体-代码优先 - Retrieve/Update EF Entity using string representation of column - code first 在数据库中存储多个枚举的最佳方法 - Best way to store multiple enums in database 隐藏字段中的值未传递到EF上下文模型 - Value from hidden field is not being passed to the EF context model 从gridview控件中隐藏字段存储和检索数据 - store and retrieve data from hidden field from gridview control JSON字符串使用枚举对象 - JSON string to object using Enums
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM