2014-04-25 64 views
3

我想實現一個屬性,我可以將其應用於我的代碼中的屬性第一個實體框架數據模型,以指示創建數據庫時將應用的唯一約束。我有read about extracting EF table mapping information使用EF 6.1公開的映射API,我有read about implementing a custom attribute to indicate which properties represent a natural key。但是,除非我誤解代碼,否則我認爲這隻有在CLR屬性名稱(OSpace/CSpace)與SQL列名稱(SSpace)匹配時纔有效。我希望能夠包括在這個例子類似EnumList我唯一鍵的關聯屬性(外鍵):Map Entity Framework代碼屬性到數據庫列(CSpace到SSpace)

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 

我已經開始與這麼多的代碼,這是基於對映射表中的鏈接文章名

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元數據框架。我希望有人更熟悉它可能會加快速度。

回答

3

我不知道這是否是完整的或可靠的,但是我終於摸索出了我的第一個測試案例工程代碼:

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 
相關問題