在EF6中使用枚举作为FK

时间:2015-09-30 08:22:51

标签: c# entity-framework entity-framework-6

我们有一个枚举Supplier

但现在我们还需要在该关系上有一些域数据

因此,在99.9%的域名代码中我们对枚举进行操作,例如product.Supplier == Suppliers.FedEx

但是现在我们还添加了product.SupplierInfo.CanAdjustPickupTime,其中SupplierInfo是一个实体,而不仅仅是一个简单的枚举类型。

我试过这些配置

Property(p => p.Supplier)
    .IsRequired()
    .HasColumnName("SupplierId");

HasRequired(p => p.SupplierInfo)
    .WithMany()
    .HasForeignKey(p => p.Supplier); //I have also tried casting to int doing .HasForeignKey(p => (int)p.Supplier)

这将失败

  

指定表达式的ResultType与   所需类型。表达式ResultType是   'MyApp.Model.Suppliers'但所需的类型是   'Edm.Int32'。参数名称:keyValues [0]

也试过

Property(l => l.Supplier)
    .IsRequired()
    .HasColumnName("SupplierId");

HasRequired(p => p.SupplierInfo)
    .WithMany()
    .Map(m => m.MapKey("SupplierId"));

这将是一个好的旧的

  

在模型生成期间检测到一个或多个验证错误:

     

SupplierId:名称:类型中的每个属性名称必须是唯一的。   已定义属性名称“SupplierId”。

我可以将SupplierId定义为使用HasForeignKey的Property属性但是我需要更改为.SuppliedId == (int)Suppliers.FedEx等。不是真正的解决方案。

我还可以添加一个使用SupplierId属性作为支持字段的属性枚举,但这不适用于Expressions,因为它需要使用实际映射的数据库属性

有什么想法吗?

3 个答案:

答案 0 :(得分:0)

我有课程:

public class Agreement
{
    public int Id { get; set; }
    public AgreementStateTypeEnum AgreementStateId { get; set; }
}

public class AgreementState
{
    public int Id { get; set; }
    public string Title { get; set; }
}

上下文:

 public class AgreementContext :DbContext
 {
     public AgreementContext() : base("SqlConnection") { }
     public DbSet<Agreement> Agreements { get; set; }
 }

在方法 OnModelCreating 中,我什么都没写。 我的枚举:

 public enum AgreementStateTypeEnum : int
 {
        InReviewing = 1,
        Confirmed = 2,
        Rejected = 3 
 }

在数据库中:表协议我有外键 AgreementStateId - 它是表 AgreementStates 的链接。 一切正常。例如:

var temp = context.Agreements.First(x => x.AgreementStateId == AgreementStateTypeEnum.Confirmed);

我使用枚举如何外键。

答案 1 :(得分:0)

最后我发现了问题。 (我使用的是EF6,NET 4.5) 因此,如果在代码中创建类型枚举,则无法与其他属性虚拟创建关系。

//This is wrong, when do you create a foreignkey using a type  enum
//Do You should remove that's code on in your class Map.
 HasRequired(p => p.SupplierInfo)
.WithMany()
.HasForeignKey(p => p.Supplier); //I have also tried casting to int doing 
.HasForeignKey(p => (int)p.Supplier)

如果您创建了类型枚举,则意味着您不需要表格返回数据来获取EF中的连接。 所以,正确的代码是:

public class MyClass{

public enum myEnumType {
FedEx,
Olther
} 

public int id {get;set;}
public myEnumType Supplier {get;set;}

}

//My class Map (using Fluent...)    
public class MyClassMap {

HasKey(t => t.Id);
Property(t => t.Id).HasColumnName("Id");
//The type [supplier] should be [int] in database.
Property(t => t.Supplier).HasColumnName("supplier");
//That's all, you don't need write relationship, int this case 
//Because, when the data returns, the EF will to do the conversion for you.

}

我希望这很有用

答案 2 :(得分:0)

我发现处理此方案的最佳方法是将供应商映射为常规域对象,并创建一个单独的已知供应商ID类。

public class KnownSupplierIds
{
    public const int FedEx = 1;
    public const int UPS = 2;
    // etc.
}

if (product.Supplier.SupplierId == KnownSupplierIds.Fedex) { ... };

当您的代码需要检查供应商时,它可以比较ID;当您需要域模型中的其他信息时,您只需加载供应商。我更喜欢使用一类常量而不是枚举的原因是该模式也适用于字符串比较,并且不需要强制转换。