使用EntityTpeConfiguration映射short []

时间:2017-10-02 19:57:43

标签: c# entity-framework ef-fluent-api

有人可以解释我应该如何使用EntityTypeConfiguration使用数组或原始值列表来映射实体。我有跟随实体和枚举:

public class PermissionForm
{
   public int Id {get; set;}

   public string Name {get; set;}

   public PermissionItem[] Permissions {get; set;}
}

public enum PermissionItem : short
{
   EDIT = 1,
   SHARE = 2,
   ADMIN = 3
}

我正在寻找类似于我试图了解它是如何工作的东西,但没有运气。

我希望数据库中的表格类似于:

| PermissionForm |
| -------------- |
| Id             |
| Name           |

|  PermissionForm_PermissionItems |
| ------------------------------- |
| PermissionFormId                |
| PermissionItem_Value            |

直到现在我得到了以下代码,但我认为不接近右边:

public PermissionForMap()
{
    this.ToTable("PermissionForm").HasKey(p => p.Id);

    this.Property(p => p.Name).HasColumnName("Name").HasMaxLength(30);
    this.Map(map =>
    {
       map.ToTable("PermissionsFormPermissionItem");
       map.Requires(p => p.Id);
       map.Properties(p => p.PermissionItems);
    });
}

1 个答案:

答案 0 :(得分:2)

枚举[Flags]

支持您的方案的最有效方法是使用Enum上的FlagsAttribute(这至少需要EntityFramework 5):

public class PermissionForm
{
   public int Id {get; set;}

   public string Name {get; set;}

   public PermissionItem Permissions {get; set;}
}

[Flags]
public enum PermissionItem : short
{
   EDIT = 1,
   SHARE = 2,
   ADMIN = 4 // note that each value must be a power of 2
}

不需要任何特定的映射:

public PermissionForMap()
{
    this.ToTable("PermissionForm").HasKey(p => p.Id);

    this.Property(p => p.Name).HasColumnName("Name").HasMaxLength(30);
    this.Property(p => p.Permissions).HasColumnName("Permissions"); // this is redundant, it's just to replicate your behavior
}

这样您就可以仅使用按位运算符& (AND)| (OR)^ (XOR)~ (complement)来管理权限。

这将简化您的模型并避免使用另一个表(这也需要在查询中加入)。

实施例

获取拥有SHARE权限的所有实体:

var query = _dbContext.PermissionForms.Where(p => p.PermissionItem & PermissionItem.SHARE > 0);

如果您使用EntityFramework 6.1+,您还可以使用内置方法HasFlag

var query = _dbContext.PermissionForms.Where(p => p.PermissionItem.HasFlag(PermissionItem.SHARE));

为实体设置多个权限:

var permission = new PermissionForm
{
    Name = "MyName",
    Permissions = PermissionItem.EDIT | PermissionItem. SHARE // this has EDIT and also SHARE
};

表映射

如果你真的想将你的关系映射到一个表(在我看来,这对你的场景来说是无用的和低效的),你需要创建一个类,实体框架作为一个实体支持这个类:

public class PermissionForm
{
   public PermissionForm()
   {
       Permissions = new HashSet<PermissionEntity>();
   }

   public int Id {get; set;}

   public string Name {get; set;}

   public virtual ICollection<PermissionEntity> Permissions {get; set;}
}

public class PermissionEntity
{
    public int PermissionFormId { get; set; }

    public PermissionItem PermissionItem { get; set; }

    public virtual PermissionForm PermissionForm { get; set; }
}

public enum PermissionItem : short
{
   EDIT = 1,
   SHARE = 2,
   ADMIN = 3
}

并将其映射为您的模型的任何其他导航属性:

public class PermissionForMap : EntityTypeConfiguration<PermissionForm>
{
    public PermissionForMap()
    {
        this.ToTable("PermissionForm").HasKey(p => p.Id);

        this.Property(p => p.Name).HasColumnName("Name").HasMaxLength(30);
        this.HasMany(p => p.Permissions) 
            .WithRequired(e => e.PermissionForm)
            .HasForeignKey(e => e.PermissionFormId);
    }
}

public class PermissionEntityMap : EntityTypeConfiguration<PermissionEntity>
{
    public PermissionEntityMap()
    {
        ToTable("PermissionEntities")
            .HasKey(e => new { e.PermissionFormId, e.PermissionItem }):
    }
}