Entity Framework Umstellung auf Code First => EF erkennt nicht gemappte Entities

  • WPF

Es gibt 8 Antworten in diesem Thema. Der letzte Beitrag () ist von kaifreeman.

    Entity Framework Umstellung auf Code First => EF erkennt nicht gemappte Entities

    Abend,

    ich bin gerade dabei einen meiner Anfängerfehler mit EF zu korrigieren. Ich hatte zu Anfang den bequemen Weg des Model First gewählt => Problem mit Migration usw. darum will ich jetzt mein Datenmodell auf CodeFirst umstellen.

    Soweit so gut ich habe alle Entitäten beisamen und auch im Modell verlinkt aber es wird immer ein Fehler vom Typ System.Data.Entity.ModelConfiguration.ModelValidationException aufgeworfen mit folgendem Inhalt:

    VB.NET-Quellcode

    1. System.Data.Entity.ModelConfiguration.ModelValidationException occurred
    2. HResult=-2146233088
    3. Message=One or more validation errors were detected during model generation:
    4. HHHB2.ListCollectionView: : EntityType 'ListCollectionView' has no key defined. Define the key for this EntityType.
    5. HHHB2.CultureInfo: : EntityType 'CultureInfo' has no key defined. Define the key for this EntityType.
    6. HHHB2.DateTimeFormatInfo: : EntityType 'DateTimeFormatInfo' has no key defined. Define the key for this EntityType.
    7. HHHB2.GroupDescription: : EntityType 'GroupDescription' has no key defined. Define the key for this EntityType.
    8. HHHB2.ItemPropertyInfo: : EntityType 'ItemPropertyInfo' has no key defined. Define the key for this EntityType.
    9. ListCollectionViews: EntityType: EntitySet 'ListCollectionViews' is based on type 'ListCollectionView' that has no keys defined.
    10. CultureInfoes: EntityType: EntitySet 'CultureInfoes' is based on type 'CultureInfo' that has no keys defined.
    11. DateTimeFormatInfoes: EntityType: EntitySet 'DateTimeFormatInfoes' is based on type 'DateTimeFormatInfo' that has no keys defined.
    12. GroupDescriptions: EntityType: EntitySet 'GroupDescriptions' is based on type 'GroupDescription' that has no keys defined.
    13. ItemPropertyInfoes: EntityType: EntitySet 'ItemPropertyInfoes' is based on type 'ItemPropertyInfo' that has no keys defined.
    14. Source=EntityFramework
    15. StackTrace:
    16. bei System.Data.Entity.Core.Metadata.Edm.EdmModel.Validate()
    17. bei System.Data.Entity.DbModelBuilder.Build(DbProviderManifest providerManifest, DbProviderInfo providerInfo)
    18. bei System.Data.Entity.DbModelBuilder.Build(DbConnection providerConnection)
    19. bei System.Data.Entity.Internal.LazyInternalContext.CreateModel(LazyInternalContext internalContext)
    20. bei System.Data.Entity.Internal.RetryLazy`2.GetValue(TInput input)
    21. bei System.Data.Entity.Internal.LazyInternalContext.InitializeContext()
    22. bei System.Data.Entity.Internal.LazyInternalContext.get_ObjectContext()
    23. bei System.Data.Entity.Internal.InternalContext.DetectChanges(Boolean force)
    24. bei System.Data.Entity.Internal.InternalContext.GetStateEntries(Func`2 predicate)
    25. bei System.Data.Entity.Internal.InternalContext.GetStateEntries()
    26. bei System.Data.Entity.Infrastructure.DbChangeTracker.Entries()
    27. bei System.Data.Entity.DbContext.GetValidationErrors()
    28. bei HHHB2.MainModel.InitMainmodel() in E:\Entwicklung\HHHB2\HHHB2\Viewmodel\MainModel.vb:Zeile 64.
    29. InnerException:


    Das ich alle Keys mit Data Annotations eingebaut habe ist geprüft, das alle zusätzlichen Routinen in den Klassen die nicht gemappt werden sollen mit <NotMapped> markiert sind habe ich auch überprüft.
    Die Entitäten "ListCollectionView", "cultureinfo" usw. sind keine Entitäten die als Klassen vorliegen, von den oben angeführten Typen wird in manchen Klassen nur die Listcollectionview genutzt => <NotMapped>

    Als Beispiel eine Klasse die als Entität im Modell vorliegt:

    VB.NET-Quellcode

    1. Imports System.ComponentModel.DataAnnotations
    2. Imports System.Collections.ObjectModel
    3. Imports System.ComponentModel.DataAnnotations.Schema
    4. Public Class category_v01
    5. Inherits model_base
    6. 'Interne Variablen
    7. Dim v_cat_id As Integer
    8. Dim v_bezeichnung As String
    9. Dim v_color As String = "#000000"
    10. Dim v_symbol As Byte()
    11. Dim v_aktiv As Nullable(Of Boolean) = True
    12. Dim v_parent_cat_id As Nullable(Of Integer)
    13. <Key>
    14. Public Property cat_id As Integer
    15. Get
    16. Return v_cat_id
    17. End Get
    18. Set(value As Integer)
    19. If v_cat_id <> value Then
    20. v_cat_id = value
    21. NotifyPropertyChanged("cat_id")
    22. End If
    23. End Set
    24. End Property
    25. Public Property bezeichnung As String
    26. Get
    27. Return v_bezeichnung
    28. End Get
    29. Set(value As String)
    30. If v_bezeichnung <> value Then
    31. v_bezeichnung = value
    32. NotifyPropertyChanged("bezeichnung")
    33. End If
    34. End Set
    35. End Property
    36. Public Property color As String
    37. Get
    38. Return v_color
    39. End Get
    40. Set(value As String)
    41. If v_color <> value Then
    42. v_color = value
    43. NotifyPropertyChanged("color")
    44. End If
    45. End Set
    46. End Property
    47. Public Property symbol As Byte()
    48. Get
    49. Return v_symbol
    50. End Get
    51. Set(value As Byte())
    52. If v_symbol IsNot value Then
    53. v_symbol = value
    54. NotifyPropertyChanged("symbol")
    55. NotifyPropertyChanged("symbol_ever")
    56. End If
    57. End Set
    58. End Property
    59. Public Property aktiv As Nullable(Of Boolean)
    60. Get
    61. Return v_aktiv
    62. End Get
    63. Set(value As Nullable(Of Boolean))
    64. If v_aktiv <> value Then
    65. v_aktiv = value
    66. NotifyPropertyChanged("aktiv")
    67. End If
    68. End Set
    69. End Property
    70. Public Property parent_cat_id As Nullable(Of Integer)
    71. Get
    72. Return v_parent_cat_id
    73. End Get
    74. Set(value As Nullable(Of Integer))
    75. If v_parent_cat_id <> value Then
    76. v_parent_cat_id = value
    77. NotifyPropertyChanged("parent_cat_id")
    78. End If
    79. End Set
    80. End Property
    81. <NotMapped>
    82. Public ReadOnly Property symbol_ever() As Byte()
    83. Get
    84. If symbol Is Nothing Then
    85. Return Resource2Byte("/Resources/Icons8/Color/Happy_50px.png") 'Nullbild
    86. Else
    87. Return symbol
    88. End If
    89. End Get
    90. End Property
    91. <NotMapped>
    92. Public ReadOnly Property solid_color() As SolidColorBrush
    93. Get
    94. If color Is Nothing Then
    95. Return New SolidColorBrush(Colors.Black)
    96. Else
    97. Try
    98. Dim v_col As System.Drawing.Color = System.Drawing.ColorTranslator.FromHtml(color)
    99. Dim v_color As Color = System.Windows.Media.Color.FromArgb(v_col.A, v_col.R, v_col.G, v_col.B)
    100. Return New SolidColorBrush(v_color)
    101. Catch ex As Exception
    102. Return New SolidColorBrush(Colors.Black)
    103. End Try
    104. End If
    105. End Get
    106. End Property
    107. 'Navigation Properties:
    108. Public Property nv_subcats As ObservableCollection(Of category_v01)
    109. <ForeignKey("parent_cat_id")>
    110. Public Property nv_subcats_back As category_v01
    111. Public Property nv_cat_trans2kat As ObservableCollection(Of trans_2_kat)
    112. Public Property transrep_2_kat2 As ObservableCollection(Of transrep_2_kat)
    113. Public Property nv_category_2_budcat As ObservableCollection(Of budget_2_cat_v01)
    114. Public Property nv_cat_2_transtemp As ObservableCollection(Of transtemp_2_kat)
    115. #Region "Sonderproperties"
    116. ''' <summary>
    117. ''' gibt den vollen Namen der kategorie mit ihrer Elternkategorie zurück
    118. ''' </summary>
    119. ''' <returns></returns>
    120. <NotMapped>
    121. Public ReadOnly Property fullname As String
    122. Get
    123. If parent_cat_id Is Nothing Then
    124. Return bezeichnung
    125. Else
    126. Return String.Concat(nv_subcats_back.bezeichnung, " - ", bezeichnung)
    127. End If
    128. End Get
    129. End Property
    130. 'Bezeichnung Properties fürs Budget:
    131. <NotMapped>
    132. Public ReadOnly Property budget_maincat_name As String
    133. Get
    134. If parent_cat_id Is Nothing Then
    135. Return bezeichnung
    136. Else
    137. Return nv_subcats_back.bezeichnung
    138. End If
    139. End Get
    140. End Property
    141. <NotMapped>
    142. Public ReadOnly Property budget_subcat_name As String
    143. Get
    144. If parent_cat_id Is Nothing Then
    145. Return ""
    146. Else
    147. Return bezeichnung
    148. End If
    149. End Get
    150. End Property
    151. <NotMapped>
    152. Public Property subcats_aktiv As ListCollectionView
    153. <NotMapped>
    154. Private WithEvents nv_subcats_helper As ObservableCollection(Of category_v01)
    155. Sub New()
    156. nv_subcats_helper = nv_subcats
    157. subcats_aktiv = New ListCollectionView(nv_subcats_helper)
    158. subcats_aktiv.LiveFilteringProperties.Add("aktiv")
    159. subcats_aktiv.IsLiveFiltering = True
    160. End Sub
    161. #End Region
    162. End Class


    Im Modell schaut es so aus:

    VB.NET-Quellcode

    1. Imports System
    2. Imports System.Data.Entity
    3. Imports System.Linq
    4. Public Class hhhb2_model
    5. Inherits DbContext
    6. Public Sub New()
    7. MyBase.New("name=hhhb2_model")
    8. Database.SetInitializer(New DropCreateDatabaseAlways(Of hhhb2_model))
    9. End Sub
    10. Public Overridable Property category_v01 As DbSet(Of category_v01)
    11. End Class


    (Modell ist stark verkürzt wegen Übersichtlichkeit)

    Als absolute Verzweiflungstat habe ich jetzt das gesamte Modell in ein neues Projekt übertragen und dort funktioniert es komischerweise....
    Hat jemand von euch einen Tipp für mich? ;(

    Danke
    sry wegen Doppelpost aber es hat sich erledigt.

    Ich habe jetzt nochmal das ganze Datenmodell durchgesehen und es Klasse für Klasse neu erstellt folgende Anweisung wurde mir zum Verhängnis (für zukünftige Generationen :S )

    VB.NET-Quellcode

    1. <NotMapped>
    2. Public WithEvents cvMixedChildren As New ListCollectionView(MixedChildren)


    wird in:

    VB.NET-Quellcode

    1. <NotMapped>
    2. Public cvMixedChildren As New ListCollectionView(MixedChildren)


    umgeschrieben funktioniert es. Warum es jetzt funktioniert ist mir erstmal nicht klar aber ich schreibe das einfach mal auf die Eigenart von EF Klassen zu durchstöbern die nicht im Modell gemapped sind.
    Z.B. beim Relaycommand hat sich EF beschwert das keine Sub New ohne Konstruktor vorhanden ist....
    Du könntest prinzipiell recht haben allerdings stelle ich mir dann die Frage warum es 1 Zeile darüber mit der ObservableCollection funktioniert...
    Geschweige denn das das Prinzip von DataAnnotations mit <NotMapped> ist das es eben ignoriert werden soll was es offensichtlich nicht tut.

    Ich kann mir das nur so vorstellen, das EF prinzipiell die gesamte Klasse und alle ihre Verweise ansieht (auch Klassen die mit Inherit auf die "Mutter" verweisen). Dann schaut ob ein Sub New ohne Konstruktor vorhanden ist und eben alle Properties durchsucht, egal was die DataAnnotations sagen. Da sich in der ListCollectionView Klasse wiederum Verweise auf die in der Eingangs erwähnten Fehlermeldung verwiesenen Klasse befinden und eventuell noch n Ebenen tiefer kommt es zum Error...

    Sinn macht es in meinen Augen zwar nicht...
    Da gibts wohl unterschiedliche Ansichten, und MS gefiel es wohl, da mal was ganz dolles rauszubringen.
    Ich seh das auch so, dass ein in einem ER-Diagramm konzipiertes Datemodell eine unschätzbare Hilfe ist, und scheint mir mehr als fragwürdig, wenn man das weglässt.
    Tatsächlich modelliert man es ja doch, nämlich indem man <Key>, <ForeignKey> und weitere Attribute setzt - nur halt ohne Überblick über die Gesamtheit der Abhängigkeiten.

    Also ich nehm lieber ein ER-Diagramm und lass daraus Code generieren - ist auch weniger Schreibarbeit.
    Ganz ehrlich ich hatte bis jetzt Model First und hab es geliebt weil die Erstellung des Modells echt simpel ist.
    Leider ist es ein Drama eine SQL Compact DB zu erstellen, das funktioniert nicht automatisch (zumindest konnte ich keinen Weg finden) und spätestens beim updaten des Modells war für mich dann Schicht im Schacht.

    Mit Code First und automated Migration habe ich den Nachteil das ich zwar alle Klassen tippen muss und eigentlich viel Schreibarbeit habe aber mit einem externen DB Planungsprogramm (z.B. DBDesigner) kann ich es optisch gut vorbereiten und relativ schnell übernehmen. Alternativ kann man eine Solution eröffnen dort mit Model First eine DB erstellen und dann mit DB First die Datenbank in Code First ableiten => automatisch. Dann braucht man in den Klassen nur mehr die Notifypropertychanged usw. implementieren und gut ist.
    sorry für den OT, aber den würd ich noch gern loswerden:
    Iwas ist doch faul daran, wenn man erst dolle CodeFirst-Technologie rausbringt, damit man keinen DB-Designer mehr benutzen muss, und dann auf einen externen Db-Designer zurückgreift, weil man eben doch einen Db-Designer braucht.
    Der externe hat halt den Nachteil, er kann kein Code generieren.

    Und ja - MS will wohl jeden an sein SqlServer-Monstrum zwingen, deshalb bringen sie so Krücken raus wie SqlCe oder LocalDb und stampfen die bisserl später wieder ein, weil doch nicht richtig funzt.
    So bleibt man denn bei SqlServer oder Access, weil da gibts brauchbare (mehr oder weniger) Db-Designer-FrontEnds zu, und die CodeGenerierung mit Connectoren funzt auch. Und mit SqlServer funzt dann wohl CodeFirst auch - genau weißichs nicht, obs da nicht doch noch Macken gibt - ich hatte zu Zeiten krasse Probleme, damit einen m:n-View hinzukriegen: EntityFramework-CodeFirst-Sample - aber kann auch an SqlCe liegen.

    Inzwischen hab ich mir einen eigenen Model-First-Ansatz zurechtgebastelt, der generiert Datenbanken aus einem designeten typisierten Dataset.

    Aber wenn von SqlCe die Rede ist: SqlCe ist ja afaik nicht multiUser-fähig, und meist kann man dann doch sein Dataset einfacher komplett auf Platte lesen/schreiben, ohne überhaupt sich einen abzukrampfen mit dem Db-Gedödel - warum ist das keine Option?
    Ich gebe dir da absolut recht, mit Model First hat man ein wunderbares Tool geschaffen ein Datenmodell grafisch zu generieren, es kann Relationen, es kann Base Klassen eigentlich alles was man so zum Leben braucht aber leider hat man es verabsäumt eine automatische Migration einzubauen (und ehrlich wer hat nicht im Nachhinein an seinem Modell was ändern müssen...).
    Der externe Designer hilft einfach nur den Überblick zu behalten. Mein Modell ist nicht sonderlich komplex es sind gerademal 26 Entitäten vorhanden aber wenn ich es ohne grafische Unterstützung gemacht hätte wäre ich spätestens bei der xten Relation gescheitert.

    Soweit ich es bis jetzt beurteilen kann funzt EF mit SQL Server und auch mit SQL Express bzw. Compact sehr gut bis auf meinen Anfangsschwierigkeiten habe ich mittlerweile ein brauchbares Programm.
    Ob SqlCE oder Lokales Dataset ist in meinen Augen relativ egal, mir ging es darum das ich eine Lösung habe bei der der User mehrere Datenbanken im Programm verwenden kann. Theoretisch wäre es auch sicher mit einem lokalen Dataset gegangen, ich finde es halt schön mit SQL direkt in der Datenbank während der Entwicklung etwas anpassen zu können aber das ist wohl eher Geschmackssache.

    Abschließend zum Thema Multiuser, MS empfiehlt bei Multiuser den SQL Express oder eben den großen SQL (download.microsoft.com/downloa…ct_Express_Comparison.doc) Der SQLCe funktioniert nur solange kein Write auf die Datei ausgeführt wird, ansonsten hebelt sich das Programm aus (zumindest meine Erfahrung). Ale Alternativ käme dann SQL Lite zur Erwähnung sqlite.org/index.html der soll Multiuser können (wobei das nachplappern ist getestet habe ich es nicht).

    Welchen DB Typ generiert dein Ansatz?