似乎我无法找到“如何使用ORM工具的EAV方法”问题的答案,所以我会在这里试试运气。
假设我有一个Entities
表:
ID -> int
Name -> nvarchar(50)
Images
表:
EntityID -> int
Width -> int
Height -> int
和Songs
表:
EntityID -> int
Duration -> decimal(12,3)
我需要向实体添加可扩展元数据(具有类型信息的未知键值对),以便我能够发出如下查询:
找到Duration
超过3分钟的所有歌曲,其中Name
以“The”开头,元数据符合以下条件:
HasGuitarSolo
设置为true GuitarSoloDuration
大于30秒按{降序排序GuitarSoloDuration
对结果进行排序。
我不想在数据库中创建HasGuitarSolo
,GuitarSoloDuration
等列。理想情况下,我希望将它们存储在类似EAV的模式中,或者替代模式中。 t需要事先知道密钥。
答案 0 :(得分:3)
在名为'metadata'的表中添加一列,并将XML放入其中。 SQL Server允许您查看一个充满XML的blob,就像它是附加列一样(有限制)。
对于ORM,它取决于对象的结构。
如果您拥有一大堆硬编码元数据属性,除了无限量之外,您还可以使用列表和反射轻松处理XML属性和MetaDataItem属性中的crud。如果所有都是硬编码的,您仍然可以使用XML文本属性来加载/保存它们,映射一个属性,而不是其他属性。
使用对象上的LINQ查询对它们进行排序。
我做得非常成功,每个子弹编码,东西越来越好! 2005 / .Net 1.1所以没有ORM,LINQ,我的第一个VB.net程序等。但是其他开发人员确实使用SQL服务器的XML查询来读取我的XML。我当然忘记了这一点,改变了它,把它们绊倒了: - (
这是片段。这一切的关键是: ORM友好= ORM一些属性,而不是其他属性;允许使用者使用其他属性,但不能使用其他属性。如果您的ORM不允许选择此类单选属性,则可以使用继承或组合来欺骗它。抱歉,我没有时间为您的目的发布完整示例。
我家里没有代码示例。我将在明天编辑并粘贴它。
按照承诺编辑,这是代码段:
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
...
答案 1 :(得分:3)
我过去通过在我的对象上放置Extra
属性来做到这一点,这是一个字典或类似的数据类型。然后,您可以使用数据自由填充此数据,并使用LINQ进行查询。
答案 2 :(得分:2)
您可以添加几个表格,如:
[EntitiesExtended]
EntitiesExtendedId int
EntitiesExtendedDescription varchar(max)
[Entities_EntitiesExtended]
Entities_EntitiesExtendedId int
EntitiesId int
EntitiesExtendedId int
EntitiesExtendedValue varchar(max)
因此,如果歌曲1的吉他独奏为34秒并且持续3分23秒,则可以建模为:
[Entities_EntitiesExtended]
EntitiesId = 1
EntitiesExtendedId = 1
EntitiesExtendedValue = "34"
EntitiesId = 1
EntitiesExtendedId = 2
EntitiesExtendedValue = "203"
[EntitiesExtended]
EntitiesExtendedId = 1
EntitiesExtendedDescription = "GuitarSoloDuration"
[EntitiesExtended]
EntitiesExtendedId = 2
EntitiesExtendedDescription = "Duration"
然后查询:
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
答案 3 :(得分:2)
您可以使用LINQ to SQL ORM将数据存储在SQL Server中。
<强>更新强> 您还可以查看NH. LLBL,这是一个ORM /生成器,您的实体将预先生成大量代码,并从数据库开始。