【问题标题】:Use enum as FK in EF6在 EF6 中使用枚举作为 FK
【发布时间】:2015-09-30 08:22:51
【问题描述】:

我们有一个枚举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 一起使用的属性,但随后我需要更改为.SuppliedId == (int)Suppliers.FedEx 等。这并不是真正的解决方案。

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

有什么想法吗?

【问题讨论】:

  • 我们解决了问题?
  • 不,到目前为止是丑陋的解决方法。很想得到这个排序
  • 我也遇到过这个问题
  • 如果您找到解决方案,请告诉我:D
  • 好的,如果我能找到:)

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


【解决方案1】:

我有课:

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 
 }

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

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

我如何使用枚举外键。

【讨论】:

  • 您的实体配置是什么样的?
  • 在我的情况下,您的协议类也将有一个指向协议状态实体的协议状态属性,它会导致问题
  • @Anders,我也有虚拟财产。但它给出了一个错误。
  • 但这不是我的问题的解决方案:D 我的问题是我想要一个具有导航属性的枚举 FK
  • 我有迁移的通用上下文。和模型的上下文。有界上下文。 CommonContext 包含具有虚拟属性和属性 int AgreementStateId 的类
【解决方案2】:

我终于找到了问题所在。 (我使用的是 EF6,NET 4.5) 因此,如果您在代码中创建类型 Enum,则无法创建与其他属性 virtual 的关系。

//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.

}

希望对你有用

【讨论】:

    【解决方案3】:

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

    public class KnownSupplierIds
    {
        public const int FedEx = 1;
        public const int UPS = 2;
        // etc.
    }
    
    if (product.Supplier.SupplierId == KnownSupplierIds.Fedex) { ... };
    

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-04-12
      • 1970-01-01
      • 2021-04-23
      • 1970-01-01
      • 2014-05-14
      • 1970-01-01
      • 1970-01-01
      • 2011-01-10
      相关资源
      最近更新 更多