地图实体框架code属性数据库列(CSpace到SSpace)实体、框架、属性、数据库

2023-09-04 03:00:31 作者:听张国荣讲鬼故事*

我想实现我可以申请物业在我的code第一实体框架数据模型来表示唯一性约束在创建数据库时将被应用的属性。我有阅读有关提取EF表映射信息使用映射API暴露EF 6.1,我有了解实现自定义的属性,以指示哪些属性重新present自然关键。但是,除非我误读了code,我认为这将只能工作在CLR属性名称(OSpace / CSpace)的SQL列名(SSpace)相匹配。我希望能够在这个例子类似EnumList我唯一的密钥包括关联属性(外键):

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

我已经开始与这么多code,这是基于对映射表名称链接的文章

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

而这足以让我需要对表名的信息,但现在我需要的CLR属性名莫名其妙链接到SQL列名,它的进展缓慢理解EF元数据框架。我希望有人更熟悉它,可加快顺水推舟。

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.

推荐答案

我不知道这是否是完整的或可靠的,但我终于摸索出了code,它适用于我的第一个测试用例:

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
 
精彩推荐
图片推荐