Entity Framework and Enum Flags - Falafel Software Blog

If you have ever had the need to store one or more possible values in a single field, you may have used the [Flags] attribute on an enum in C# which would look something like this:

C#

[Flags]
public enum ColorFlags
{
Red = 1,
Orange = 2,
Yellow = 4,
Green = 8,
Blue = 16,
Indigo = 32,
Violet = 64
}

1

2

3

4

5

6

7

8

9

10

11

[Flags]

public enum ColorFlags

{

Red = 1,

Orange = 2,

Yellow = 4,

Green = 8,

Blue = 16,

Indigo = 32,

Violet = 64

}

The numeric values that we assign are important, because it allows us to do bit-wise operations on the number.  The values themselves can easily be calculated by raising 2 to the power of a zero-based sequence of numbers.  So this:

2?, 21, 22, 23, 2?, 2?, 2?

yields this (yes, 2 to the zero power is one):

1, 2, 4, 8, 16, 32, 64

When we talk about doing a bit-wise comparison, I find it easier to understand when I see these numbers written in binary:

0000001 = 1
0000010 = 2
0000100 = 4
0001000 = 8
0010000 = 16
0100000 = 32
1000000 = 64

1

2

3

4

5

6

7

0000001 = 1

0000010 = 2

0000100 = 4

0001000 = 8

0010000 = 16

0100000 = 32

1000000 = 64

As you can see, each of these numbers hold only a single 1 value in each position.  This is what will allow us to store any combination of these values and still determine which of the individual values a number contains.  For example, the value 3 (0000011) indicates that the two first options are set (Red and Orange).

When we store this value in the database, it is simply a number and for our example, we will never exceed the sum of those values (1111111 in binary, or 127 in decimal) so we could store it as a tinyint, but a smallint would give us room to add more values without the need to change our data type.

If we are only working with our Flags Enum in C#, we can use the Enum.HasFlag() method to determine if our value has a certain enum value:

C#

public bool IsPrimaryColor(ColorFlags color)
{
ColorFlags primaryColors = ColorFlags.Blue | ColorFlags.Green | ColorFlags.Red;
return primaryColors.HasFlag(color);
}

1

2

3

4

5

public bool IsPrimaryColor(ColorFlags color)

{

ColorFlags primaryColors = ColorFlags.Blue | ColorFlags.Green | ColorFlags.Red;

return primaryColors.HasFlag(color);

}

In the method above, we use a bit-wise OR to combine the values of the primary colors and then use HasFlag() to see if the color passed into the method matches any of the binary values of the primary colors.  And since we are using a ColorFlags enum as the parameter, you can even use HasFlag to compare any combination of values.

Flags and Entity Framework

This all works great in C#, but we have to take a different approach if we are using Linq to Entities because HasFlag() is not available to us.  Fortunately, SQL Server and Entity Framework support bit-wise operations, so we can use the single “&” to see if the stored value has the bit position that matches our value.

The example below shows how we would query for records that match ALL of the specified colors.  It will include records that may have additional colors specified, but they must have at a minimum Blue and Red set.  This is because we are comparing the AND-ed bits against the original colorsToMatch value:

C#

// Only return records that have ALL specified colors
ColorFlags colorsToMatch = ColorFlags.Blue | ColorFlags.Red;
var matchingColors = db.Cars.Where(c => c.Color & colorsToMatch == colorsToMatch);

1

2

3

// Only return records that have ALL specified colors

ColorFlags colorsToMatch = ColorFlags.Blue | ColorFlags.Red;

var matchingColors = db.Cars.Where(c => c.Color & colorsToMatch == colorsToMatch);

If we instead want to return cars that have ANY of the specified colors, we just need to check to see if the & operation is not zero.  If any of the bit positions match, it will return the sum of those values, but we don’t care if it is exactly the same as the colorsToMatch value, only that it isn’t zero meaning that there is at least one color that matches:

C#

// Return records that have ANY of the specified colors
ColorFlags colorsToMatch = ColorFlags.Blue | ColorFlags.Red;
var matchingColors = db.Cars.Where(c => c.Color & colorsToMatch != 0);

1

2

3

// Return records that have ANY of the specified colors

ColorFlags colorsToMatch = ColorFlags.Blue | ColorFlags.Red;

var matchingColors = db.Cars.Where(c => c.Color & colorsToMatch != 0);

Additional Recommendations

A few things to keep in mind when using Flag Enums with Entity Framework:

  1. Start your Flags Enum values with one, not zero.  Otherwise, you won’t be able to match the first value.  The exception is if you want to provide a “None” option.
  2. Remember that your data will be stored as a number in the database so use a datatype that can accommodate all of your values with room to add more, if necessary.
  3. Be aware of the differences between matching ANY of the flag values vs. ALL of the flag values.

转载:http://blog.falafel.com/entity-framework-enum-flags/

The following two tabs change content belo

来自为知笔记(Wiz)

时间: 2024-12-26 13:07:13

Entity Framework and Enum Flags - Falafel Software Blog的相关文章

[转]Creating an Entity Framework Data Model for an ASP.NET MVC Application (1 of 10)

本文转自:http://www.asp.net/mvc/overview/older-versions/getting-started-with-ef-5-using-mvc-4/creating-an-entity-framework-data-model-for-an-asp-net-mvc-application Creating an Entity Framework Data Model for an ASP.NET MVC Application (1 of 10) By      

Entity Framework 6.0 对枚举的支持/实体添加后会有主键反回

实验 直接上代码,看结果 实体类 [Flags] public enum FlagsEnum { Day = 1, Night = 2 } public class EntityWithEnum { public int ID { get; set; } public FlagsEnum ValidTime { get; set; } } 数据库上下文 public partial class CodeFirstModel : DbContext { public CodeFirstModel(

Entity Framework技巧系列之六 - Tip 20 – 25

提示20. 怎样处理固定长度的主键 这是正在进行中的Entity Framework提示系列的第20篇. 固定长度字段填充: 如果你的数据库中有一个固定长度的列,例如像NCHAR(10)类型的列,当你进行一次插入时,填充会自动发生.所以例如如果你插入'12345',你将得到5个自动填充的空格,来创建一个10个字符长度的字符串. 大多数情况下,这种自动填充不会有问题.但是在使用Entity Framework时如果你使用这些列的一个作为你的主键,你可能会在进行标识识别(identity resol

Why you should use async tasks in .NET 4.5 and Entity Framework 6

Improve response times and handle more users with parallel processing Building a web application using non blocking calls to the data layer is a great way to increase the scalability of your system. Performing a task asynchronously frees up the worke

Solving the Detached Many-to-Many Problem with the Entity Framework

Introduction This article is part of the ongoing series I've been writing recently, but can be read as a standalone article.  I'm going to do a better job of integrating the changes documented here into the ongoing solution I've been building. Howeve

[转]Porting to Oracle with Entity Framework NLog

本文转自:http://izzydev.net/.net/oracle/entityframework/2017/02/01/Porting-to-Oracle-with-Entity-Framework.html We had to port our giant-_ish_, Entity Framework based application to work on Oracle RDBMS (11g, later 12c). We did it. And we learned a lot.

Inheritance in Entity Framework: Table per Hierarchy

source Link Introduction This is the Entity Framework article series. In our previous two articles we learned various approaches to working with Entity Framework and various strategies to handle a database in a code first approach. You can read it he

MVC5 Entity Framework学习之创建复杂的数据模型

Contoso University示例程序演示了如何使用Entity Framework 6 Code First 和 Visual Studio 2013创建ASP.NET MVC 5应用程序. 在上一篇文章中你已经创建了由三个实体组成的简单的数据模型.在本文章中你将会添加更多的实体和关系,并且通过指定格式.验证和数据库映射规则来自定义数据模型.这里介绍两种自定义数据模型的方法:向实体类中添加属性和向数据库上下文类中添加代码. 下面是完成后的数据模型类图 1.使用属性来自定义数据模型 在本节

[转]Entity Framework and SQL Azure

本文转自:https://msdn.microsoft.com/zh-cn/library/gg190738 Julie Lerman http://thedatafarm.com April 2011 As part of Microsoft’s Azure platform, SQL Azure is your relational database in the cloud. In fact, SQL Azure is very close to being SQL Server in t