使用 EntityTypeConfiguration 映射 short[]
Mapping short[] with EntityTpeConfiguration
有人可以解释我应该如何使用 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);
});
}
枚举 [Flags]
支持您的方案的最有效方法是使用上面有 FlagsAttribute
的 Enum
(这至少需要 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
) and ~
(complement)。
这将简化您的模型并避免使用另一个 table(这也需要在您的查询中加入)。
例子
获取所有拥有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
};
Table映射
如果你真的想将你的关系映射到一个table(在我看来,这对你的场景来说是无用且低效的),你需要创建一个class,这是支持的由 EntityFramework 作为一个实体:
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 }):
}
}
有人可以解释我应该如何使用 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);
});
}
枚举 [Flags]
支持您的方案的最有效方法是使用上面有 FlagsAttribute
的 Enum
(这至少需要 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
) and ~
(complement)。
这将简化您的模型并避免使用另一个 table(这也需要在您的查询中加入)。
例子
获取所有拥有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
};
Table映射
如果你真的想将你的关系映射到一个table(在我看来,这对你的场景来说是无用且低效的),你需要创建一个class,这是支持的由 EntityFramework 作为一个实体:
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 }):
}
}