2010-12-13 14 views
12

"ORA araçlarıyla EAV yaklaşımını nasıl kullanacağım" sorusuna herhangi bir cevap bulamıyorum, bu yüzden şansımı deneyeceğim. Varsayalım.NET'te genişletilebilir meta verileri ORM dostu bir şekilde nasıl depolanır?

Bir Entities Tablo vardır:

ID -> int 
Name -> nvarchar(50) 

bir Images Tablo:

EntityID -> int 
Width -> int 
Height -> int 

Ve Songs Tablo: Ben kuruluşlara genişletilebilir meta verileri eklemek gerekir

EntityID -> int 
Duration -> decimal(12,3) 

(Ben tür bilgisi ile bilinmeyen anahtar-değer çiftleri), böylece ben bir gibi ble sorunu sorgular:

meta yerine getiren bu kriterlere sahip '' ile başlayan Bana Name ile Duration uzun 3 dakikadan olan tüm Şarkılar, bul:

  • HasGuitarSolo true olarak ayarlanır
  • GuitarSoloDuration 30 saniyeden uzun

Ve azalan sırada GuitarSoloDuration sonuçları sıralamak olduğunu.

ben veritabanında HasGuitarSolo, GuitarSoloDuration vb sütunlar oluşturmak istemiyoruz, İdeal bir EAV benzeri şema veya anahtarların bilgisi gerektirmeyen alternatif bir şemada bunları saklamak istiyorum ön tarafa.

cevap

3

'meta' olarak adlandırılan tablolar bir sütun ekleyin ve içine XML koydu. SQL sunucusu, XML ile dolu bir bloğa, ek sütunlarmış gibi (sınırlamalarla) bakmanıza olanak tanır.

ORM için, nesnenizin nasıl yapılandırıldığına bağlıdır.

  • Sonsuz Özelleştirilebilir meta veri öğeleri: Bir koleksiyondaki XML'den ad-değer çiftlerini koyarsınız. ORM'niz buna izin vermezse, bir string özelliğine koyun, setter bir XML dokümanı (veya hıza ihtiyacınız varsa daha hızlı bir nesne) olarak ayrıştırabilir. Getter dizgeyi döndürürdü. Daha sonra, ORM'd olmayan ayrı bir 'MetaDataItem (ItemName-> string)' meta veri listesindeki değerleri okur ve bunları setter ile günceller/ekler.
  • Metadeta, kodlanmış özelliklerdir - bunları XML'den çeken bir sorgu kullanarak eşleştirin.
  • Bazı öğelerin iki kodlu özelliklerinin melezi - ayarlayıcıları/alıcıları MetaDataItem'i çağırır.
  • Belirli özelliklerin doğrudan depolanması gerektiğinde ters hibrit (özellikle büyük listelerde sıralama yapıyorsanız): Bu meta veriler için özellikleri kendi özel üyeleriyle sabitlemeniz gerekir, ancak bu özellikleri ORM yapma. Bu değerlerin, ORM'd olan string özelliğine kaydedilmesini/yüklenmesini kodladı ve bu sabit kodlanmış meta veri öğelerini MetaDataItem özelliğinden de güncelleyebilmeniz için bunları da işaretleyin! Sonsuz miktara ek olarak, sabit kodlu meta özellikleri bir sürü varsa

yapabilirsiniz kolay listeleri ve yansıma ile XML mülkiyet ve MetaDataItem özelliğinde crud. Tümü kodlanmışsa, bunları yüklemek/kaydetmek için XML metin özelliğini kullanabilirsiniz, başkalarına değil, bir özelliği eşleştirin.

Nesnede bir LINQ sorgusu ile sıralayın.

Bunu büyük bir başarı ile yaptım ve her bir mermi kodlu, daha iyi ve daha iyi çalıştı! 2005/.Net 1.1 yani ORM, LINQ, ilk VB.net programımı vb. Ancak diğer geliştiriciler, XML sunucumu XML sunucumda XML'imi okumak için kullandılar. . Tabii ki, bu unutmuştum onu ​​değişti ve burada

snippet'leridir bu her anahtar :-(onları takıldı geçerli: ORM dostu = bazı özelliklerini, diğerlerini ORM; tüketiciler diğer özellikleri kullanmasına izin verin, ancak ORM'niz bu tür alabalık özellik seçimine izin vermiyorsa, aldatmak için kompozisyon veya kompozisyon kullanabilirsiniz. Maalesef amacınız için tam örnek göndermek için zamanım yok

Buradaki kod örneğini evde yok.Önemli bir şekilde düzenleyip yapıştıracağım, söz verdiğim gibi, söz veriyorum. Kod parçacığı:

Public Property ItemType(ByVal stTagName As String) As String 
     Get 
      Dim obj As Object 
      obj = Me.lstMemberList.Item(stTagName) 
      If Not obj Is Nothing Then 
       Return CType(obj, foDataItem).Type 
      End If 
     End Get 
     Set(ByVal Value As String) 
      Dim obj As Object 
      obj = Me.lstMemberList.Item(stTagName) 
      If Not obj Is Nothing Then 
       CType(obj, foDataItem).Type = Value 
      End If 
     End Set 
    End Property 

    Public Function ItemExists(ByVal stTagName As String) As Boolean 
     Return Me.lstMemberList.ContainsKey(stTagName) 
    End Function 

    Public Property ItemValue(ByVal stTagName As String, Optional ByVal Type4NewItem As String = "") As String 
     Get 
      Dim obj As Object 
      obj = Me.lstMemberList.Item(stTagName) 
      If obj Is Nothing Then 
       Dim stInternalKey As String = "" 
       Try 
        stInternalKey = Me.InternalKey.ToString 
       Catch 
       End Try 
       If stTagName <> "InternalKey" Then '' // avoid deadlock if internalkey errs! 
        Throw New ApplicationException("Tag '" & stTagName & _ 
         "' does not exist in FO w/ internal key of " & stInternalKey) 
       End If 
      Else 
       Return CType(obj, foDataItem).Value 
      End If 
     End Get 
     Set(ByVal Value As String) 
      '' // if child variation form... 
      If bLocked4ChildVariation Then 
       '' // protect properties not in the list of allowed updatable items 
       If Not Me.GetChildVariationDifferentFields.Contains(stTagName) Then 
        Exit Property 
       End If 
      End If 
      '' // WARNING - DON'T FORGET TO UPDATE THIS LIST OR YOU WILL NEVER FIND THE BUG! 
      Select Case stTagName 
       Case "PageNum" 
        _PageNum = CInt(Value) 
       Case "Left" 
        _Left = CInt(Value) 
       Case "Top" 
        _Top = CInt(Value) 
       Case "Width" 
        _Width = CInt(Value) 
       Case "Height" 
        _Height = CInt(Value) 
       Case "Type" 
        _Type = String2Type(Value) 
       Case "InternalKey" 
        _InternalKey = CInt(Value) 
       Case "UniqueID" 
        _UniqueID = Value 
      End Select 
      Static MyError As frmErrorMessage 
      Dim obj As Object 
      If Me.lstMemberList.ContainsKey(stTagName) Then 
       Dim foi As foDataItem = CType(Me.lstMemberList.Item(stTagName), foDataItem) 
       If foi.Type = "Number" Then 
        Value = CStr(Val(Value)) 
       End If 
       If foi.Value <> Value Then 
        If bMonitorRefreshChanges Then 
         LogObject.LoggIt("Gonna Send Update for Change " & stTagName & " from " & _ 
          foi.Value & " to " & Value) 
         If Not Me.FormObjectChanged_Address Is Nothing Then 
          FormObjectChanged_Address(Me, stTagName) 
         End If 
        End If 
       End If 
       foi.Value = Value 
      Else 
       Me.lstMemberList.Add(stTagName, New foDataItem(Value, Type4NewItem)) 
       Me.alOrderAdded.Add(stTagName) 
      End If 
     End Set 
    End Property 


    Public Function StringVal(ByVal st As String, Optional ByVal stDefault As String = "") As String 
     Try 
      StringVal = stDefault 
      Return CType(Me.ItemValue(st), String) 
     Catch ex As Exception 
      Dim bThrowError As Boolean = True 
      RaiseEvent ConversionError(ex, "String=" & Me.ItemValue(st), Me, st, bThrowError) 
      If bThrowError Then 
       LogObject.LoggIt("Error setting tag value in fo.StringVal: " & st) 
       Throw New Exception("Rethrown Exception getting value of " & Me.ID & "." & st, ex) 
      End If 
     End Try 
    End Function 
    Public Function IntVal(ByVal st As String, Optional ByVal iDefault As Integer = 0) As Integer 

    ... 

'' // 'native' values - are normal properties instead of XML properties, which 
    '' // actually makes it harder to deal with b/c of extra updates to sync them, BUT, 
    '' // worth it - as they are read much more than written (sorts, wizard builds, 
    '' // screen redraws, etc) I can afford to be slow when writing to them, PLUS 
    '' // retain the benefits of referencing everything else via ItemValue, PLUS 
    '' // these are just the more 'popular' items. 
    Private _Top As Integer 
    Private _Left As Integer 
    Private _Width As Integer 
    Private _Height As Integer 
    Private _PageNum As Integer 
    Private _Type As pfoType 
    Private _InternalKey As Integer 
    Private _UniqueID As String 

    Public Sub SetNativeValuesFromMyXML() 
     _Top = CInt(CType(Me.lstMemberList("Top"), foDataItem).Value) 
     _Left = CInt(CType(Me.lstMemberList("Left"), foDataItem).Value) 
     _Width = CInt(CType(Me.lstMemberList("Width"), foDataItem).Value) 
     _Height = CInt(CType(Me.lstMemberList("Height"), foDataItem).Value) 
     _PageNum = CInt(CType(Me.lstMemberList("PageNum"), foDataItem).Value) 
     _Type = String2Type(CType(Me.lstMemberList("Type"), foDataItem).Value) 
     _InternalKey = CInt(CType(Me.lstMemberList("InternalKey"), foDataItem).Value) 
     _UniqueID = CType(Me.lstMemberList("UniqueID"), foDataItem).Value 
    End Sub 

    Public Property Top() As Integer 
     Get 
      Return _Top '' // CInt(ItemValue("Top")) 
     End Get 
     Set(ByVal Value As Integer) 
      ItemValue("Top") = Value.ToString 
     End Set 
    End Property 

    Public Property Left() As Integer 
     Get 
      Return _Left '' //CInt(ItemValue("Left")) 
     End Get 

    ... 
2

Sen gibi tablolar birkaç ekleyebilirsiniz:

[Entities_EntitiesExtended] 
EntitiesId = 1 
EntitiesExtendedId = 1 
EntitiesExtendedValue = "34" 

EntitiesId = 1 
EntitiesExtendedId = 2 
EntitiesExtendedValue = "203" 

[EntitiesExtended] 
EntitiesExtendedId = 1 
EntitiesExtendedDescription = "GuitarSoloDuration" 

[EntitiesExtended] 
EntitiesExtendedId = 2 
EntitiesExtendedDescription = "Duration" 
: Şarkı id 1 34 saniyelik bir gitar solosu vardı ve modellenmiştir 3 dakika ve 23 saniye süren
[EntitiesExtended] 
EntitiesExtendedId int 
EntitiesExtendedDescription varchar(max) 

[Entities_EntitiesExtended] 
Entities_EntitiesExtendedId int 
EntitiesId int 
EntitiesExtendedId int 
EntitiesExtendedValue varchar(max) 

Yani eğer

gibi

ve sonra sorgular:

select * from Entities e 
join Entities_EntitiesExtended eee on e.id = eee.id 
join EntitiesExtended ee on eee.id = ee.id 
where EntitiesExtendedDescription = "GuitarSoloDuration" 
and cast(EntitiesExtendedValue as int) > 30 

select * from Entities e 
join Entities_EntitiesExtended eee on e.id = eee.id 
join EntitiesExtended ee on eee.id = ee.id 
where EntitiesExtendedDescription = "Duration" 
and cast(EntitiesExtendedValue as int) > 180 
+1

SQL'de bu nasıl yapılabilir. Özellikle ORM dostu bir şekilde arıyorum. Döküm ne SQL ne de O/R haritacıları için çok samimi görünmüyor. Yardım etmeye çalıştığınız için teşekkürler. –

+0

@Marcin Seredynski: Verileri nerede saklamak o zaman? – sv88erik

+0

@ sv88erik: "SQL'de bitti" ile, sorguları el ile yazmıştım, akılda herhangi bir spesifik veritabanı motoru yoktu (eğer demek istediyseniz buysa). Veri ilişkisel bir veritabanında saklanmalıdır. Verilere erişim, sunucu tarafında döküm gerektirmemelidir. İdeal olarak, uygun CLR türlerini uygun SQL sütun türlerinde depolamak mümkün olmalıdır. –

2

SQL Server ve LINQ to SQL ORM kullanarak verileri saklayabilir. Güncelleme

: Ayrıca NH. LLBL bakmak olabilir, bu kişiler kod çok önceden oluşturulmuş olacak ve bu veritabanından başlar bir ORM/Jeneratör olduğunu.

+0

v3 (Mayıs 2010'da yayınlanmıştır), LLBLGen Pro, aynı zamanda, ilişkisel modelleri güncellemek ve oluşturmak için kullanılabilecek model ilk modelleme özelliklerini de sunar. –

3

Bunu, bir Sözlük veya benzer veri türü olan bir nesneye Extra özelliği ekleyerek geçmişte yaptım. Daha sonra bunu verilerle serbestçe doldurabilir ve LINQ kullanarak sorgulayabilirsiniz.

+0

IDictionary veya IDictionaty benim hedeflediğim şey. Soru, ORM dostu bir şema oluşturmayla ilgili idi. Biraz daha açıklayabilirseniz gerçekten çok memnun olurum? –