将实体框架代码属性映射到数据库列(CSpace到SSpace) [英] Map Entity Framework code properties to database columns (CSpace to SSpace)

查看:75
本文介绍了将实体框架代码属性映射到数据库列(CSpace到SSpace)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试实现一个属性,我可以应用到我的代码中的属性第一个Entity Framework数据模型,以指示创建数据库时将应用的唯一约束。我有阅读关于提取EF表映射信息使用为EF 6.1公开的映射API,我已经阅读有关实现自定义属性以指示哪些属性表示自然键<一>。但是,除非我误读了代码,我认为这只有当CLR属性名称(OSpace / CSpace)与SQL列名称(SSpace)匹配时才有效。我希望能够在我的唯一键中包含关联属性(外键),例如EnumList:

 公共类EnumValue 
公共属性EnumValueId As Integer
公共属性序列为整数
公共可覆盖属性标签为TranslatedString
< MaxLength(5),MyUnique()> _
公共属性值As String
< MyUnique()> _
公共覆盖属性枚举列表作为枚举
结束类

我已经开始使用这么多代码,它基于关于映射表名称的链接文章。

  Dim ws = DirectCast(context,System.Data .Entity.Infrastructure.IObjectContextAdapter).ObjectContext.MetadataWorkspace 
Dim oSpace = ws.GetItemCollection(Core.Metadata.Edm.DataSpace.OSpace)
Dim entityTypes = oSpace.GetItems(Of EntityType)()
Dim entityContainer = ws.GetItems(Of EntityContainer)(DataSpace.CSpace).Single()
Dim mapping = ws.GetItems(Of EntityContainerMapping)(DataSpace.CSSpace).Single.EntitySetMappings
对于每个setType在entityTypes
Dim cSpaceEntitySet = entityContainer.EntitySets.Single(Function(t)t.ElementType.Name = setType.Name)
Dim sSpaceEntitySet = mapping.Single(Function(t)t.EntitySet是cSpaceEntitySet )
Dim tableInfo = sSpaceEntitySet.EntityTypeMappings.Single.Fragments.Single
D im tableName = If(tableInfo.StoreEntitySet.Table,tableInfo.StoreEntitySet.Name)
Dim schema = tableInfo.StoreEntitySet.Schema

这足以获取有关表名称的信息,但现在我需要以某种方式将CLR属性名称链接到SQL列名称,并且了解EF元数据框架的速度很慢。我希望更熟悉的人可能会加快速度。

解决方案

我不知道是否完整或可靠,但是我终于找出了适用于我的第一个测试用例的代码:

  Dim ws = DirectCast(context,System.Data .Entity.Infrastructure.IObjectContextAdapter).ObjectContext.MetadataWorkspace 
Dim oSpace = ws.GetItemCollection(Core.Metadata.Edm.DataSpace.OSpace)
Dim entityTypes = oSpace.GetItems(Of EntityType)()
Dim entityContainer = ws.GetItems(Of EntityContainer)(DataSpace.CSpace).Single()
Dim entityMapping = ws.GetItems(Of EntityContainerMapping)(DataSpace.CSSpace).Single.EntitySetMappings
Dim关联= ws.GetItems(EntityContainerMapping)(DataSpace.CSSpace).Single.AssociationSetMappings
对于每个setType在entityTypes
Dim cSpaceEntitySet = entityContainer.EntitySets.SingleOrDefault(_
Function(t)t。 ElementType.Name = setType.Name)
如果cSpaceEntitySet是Nothing然后继续为'派生实体将被跳过
Dim sSpaceEntitySet = entityMapping.Single(函数(t)t.EntitySet是cSpaceEntitySet)
Dim tableInfo As MappingFragment
如果sSpaceEntitySet.EntityTypeMappings .Count = 1然后
tableInfo = sSpaceEntitySet.EntityTypeMappings.Single.Fragments.Single
Else
'只选择映射(esp。 PropertyMappings)为基类
tableInfo = sSpaceEntitySet.EntityTypeMappings.Where(Function(m)m.IsOfEntityTypes.Count _
= 1 AndAlso m.IsOfEntityTypes.Single.Name为setType.Name).Single( ).Fragments.Single
End If
Dim tableName = If(tableInfo.StoreEntitySet.Table,tableInfo.StoreEntitySet.Name)
Dim schema = tableInfo.StoreEntitySet.Schema
Dim clrType = Type.GetType(setType.FullName)
Dim uniqueCols As IList(Of String)= Nothing
对于每个propMap在tableInfo.PropertyMappings.OfType(Of ScalarPropertyMapping)()
Dim clrProp = clrType .GetProperty(propMap.Property.Name)
如果Attribute.GetCustomAttribute(clrProp,GetType(UniqueAttribute))IsNot Nothing Then
如果uniqueCols是Nothing然后uniqueCols =新列表(String)
uniqueCols .Add(propMap.Column.Name)
End If
Next
对于每个navProp在setType.NavigationProperties
Dim clrProp = clr Type.GetProperty(navProp.Name)
如果Attribute.GetCustomAttribute(clrProp,GetType(UniqueAttribute))IsNot Nothing Then
Dim assocMap = associations.SingleOrDefault(function(a)_
a.AssociationSet .ElementType.FullName = navProp.RelationshipType.FullName
Dim sProp = assocMap.Conditions.Single
如果uniqueCols是Nothing然后uniqueCols =新列表(String)
uniqueCols.Add(sProp。 Column.Name)
End If
Next
如果uniqueCols IsNot Nothing然后
Dim propList = uniqueCols.ToArray()
context.Database.ExecuteSqlCommand(CREATE UNIQUE INDEX IX_& tableName& _& String.Join(_,propList)_
& ON&模式& &安培; tableName& (& String.Join(,,propList)&))
结束如果
下一个


I am trying to implement an attribute that I can apply to properties in my code first Entity Framework data model to indicate unique constraints that will be applied when the database is created. I have read about extracting EF table mapping information using the mapping API exposed for EF 6.1, and I have read about implementing a custom attribute to indicate which properties represent a natural key. But, unless I'm misreading the code, I think this will only work when the CLR property name (OSpace / CSpace) matches the SQL column name (SSpace). I would like to be able to include association properties (foreign keys) in my unique key like EnumList in this example:

Public Class EnumValue
   Public Property EnumValueId As Integer
   Public Property Sequence As Integer
   Public Overridable Property Label As TranslatedString
   <MaxLength(5), MyUnique()> _
   Public Property Value As String
   <MyUnique()> _
   Public Overridable Property EnumList As EnumList
End Class

I've started with this much code, which it based on the linked article about mapping table names

Dim ws = DirectCast(context, System.Data.Entity.Infrastructure.IObjectContextAdapter).ObjectContext.MetadataWorkspace
Dim oSpace = ws.GetItemCollection(Core.Metadata.Edm.DataSpace.OSpace)
Dim entityTypes = oSpace.GetItems(Of EntityType)()
Dim entityContainer = ws.GetItems(Of EntityContainer)(DataSpace.CSpace).Single()
Dim mapping = ws.GetItems(Of EntityContainerMapping)(DataSpace.CSSpace).Single.EntitySetMappings
For Each setType In entityTypes
   Dim cSpaceEntitySet = entityContainer.EntitySets.Single(Function(t) t.ElementType.Name = setType.Name)
   Dim sSpaceEntitySet = mapping.Single(Function(t) t.EntitySet Is cSpaceEntitySet)
   Dim tableInfo = sSpaceEntitySet.EntityTypeMappings.Single.Fragments.Single
   Dim tableName = If(tableInfo.StoreEntitySet.Table, tableInfo.StoreEntitySet.Name)
   Dim schema = tableInfo.StoreEntitySet.Schema

And that's enough to get the information I need about the table name, but now I need to somehow link the CLR property name to the SQL column name, and it's slow going understanding the EF metadata framework. I'm hoping that someone more familiar with it might speed things along.

解决方案

I'm not sure if it's complete or reliable, but I finally worked out the code that works for my first test case:

Dim ws = DirectCast(context, System.Data.Entity.Infrastructure.IObjectContextAdapter).ObjectContext.MetadataWorkspace
Dim oSpace = ws.GetItemCollection(Core.Metadata.Edm.DataSpace.OSpace)
Dim entityTypes = oSpace.GetItems(Of EntityType)()
Dim entityContainer = ws.GetItems(Of EntityContainer)(DataSpace.CSpace).Single()
Dim entityMapping = ws.GetItems(Of EntityContainerMapping)(DataSpace.CSSpace).Single.EntitySetMappings
Dim associations = ws.GetItems(Of EntityContainerMapping)(DataSpace.CSSpace).Single.AssociationSetMappings
For Each setType In entityTypes
   Dim cSpaceEntitySet = entityContainer.EntitySets.SingleOrDefault( _
      Function(t) t.ElementType.Name = setType.Name)
   If cSpaceEntitySet Is Nothing Then Continue For ' Derived entities will be skipped
   Dim sSpaceEntitySet = entityMapping.Single(Function(t) t.EntitySet Is cSpaceEntitySet)
   Dim tableInfo As MappingFragment
   If sSpaceEntitySet.EntityTypeMappings.Count = 1 Then
      tableInfo = sSpaceEntitySet.EntityTypeMappings.Single.Fragments.Single
   Else
      ' Select only the mapping (esp. PropertyMappings) for the base class
      tableInfo = sSpaceEntitySet.EntityTypeMappings.Where(Function(m) m.IsOfEntityTypes.Count _
         = 1 AndAlso m.IsOfEntityTypes.Single.Name Is setType.Name).Single().Fragments.Single
   End If
   Dim tableName = If(tableInfo.StoreEntitySet.Table, tableInfo.StoreEntitySet.Name)
   Dim schema = tableInfo.StoreEntitySet.Schema
   Dim clrType = Type.GetType(setType.FullName)
   Dim uniqueCols As IList(Of String) = Nothing
   For Each propMap In tableInfo.PropertyMappings.OfType(Of ScalarPropertyMapping)()
      Dim clrProp = clrType.GetProperty(propMap.Property.Name)
      If Attribute.GetCustomAttribute(clrProp, GetType(UniqueAttribute)) IsNot Nothing Then
         If uniqueCols Is Nothing Then uniqueCols = New List(Of String)
         uniqueCols.Add(propMap.Column.Name)
      End If
   Next
   For Each navProp In setType.NavigationProperties
      Dim clrProp = clrType.GetProperty(navProp.Name)
      If Attribute.GetCustomAttribute(clrProp, GetType(UniqueAttribute)) IsNot Nothing Then
         Dim assocMap = associations.SingleOrDefault(Function(a) _
            a.AssociationSet.ElementType.FullName = navProp.RelationshipType.FullName)
         Dim sProp = assocMap.Conditions.Single
         If uniqueCols Is Nothing Then uniqueCols = New List(Of String)
         uniqueCols.Add(sProp.Column.Name)
      End If
   Next
   If uniqueCols IsNot Nothing Then
      Dim propList = uniqueCols.ToArray()
      context.Database.ExecuteSqlCommand("CREATE UNIQUE INDEX IX_" & tableName & "_" & String.Join("_", propList) _
         & " ON " & schema & "." & tableName & "(" & String.Join(",", propList) & ")")
   End If
Next

这篇关于将实体框架代码属性映射到数据库列(CSpace到SSpace)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆