Entity Inheritance + EntityModelCodeGenerator
-
Monday, December 03, 2007 8:10 PM
Hi,
I'm using EF Beta 2 + VS 2008 beta 2. Trying to get entity inheritence to work and have got to the point where the csdl, ssdl, and msl seem to agree with each other. however the auto generated code seems to be missing the properties for the inherited entity types. Just to be clear it is the properties for the inherited entities in the ContextObject that are not created automatically, the classes are something like this
Namespace
TestModel '''<summary> '''There are no comments for DirectNewsEntities in the schema. '''</summary> Partial Public Class TestEntities Inherits Global.System.Data.Objects.ObjectContext.
.
.
<
Global.System.ComponentModel.BrowsableAttribute(false)> _ Public ReadOnly Property AnimalBase() As Global.System.Data.Objects.ObjectQuery(Of AnimalBase) Get If (Me._AnimalBase Is Nothing) Then Me._AnimalBase= MyBase.CreateQuery(Of AnimalBase)("[AnimalBase]") End If Return Me._AnimalBase End Get End Property Private _AnimalBaseAs Global.System.Data.Objects.ObjectQuery(Of AnimalBase) = Nothing.
.
.
End Class
Partial
Public MustInherit Class ArticlesBaseDATAInherits
Global.System.Data.Objects.DataClasses.EntityObject.
.
.
End
Class
Partial Public Class Dog Inherits AnimalBase Public Shared Function CreateDog(ByVal iD As Integer) As Dog Dim dog As Dog= New Dogdog.ID = iD
Return dog End Function End ClassIn the partial class "AnimalEntities"I expected to see a readonly property called "Dog"
What I would like to know is if this code just isn't generated in beta? if this is the case I suppose i can write a partial class that adds the required properties to the auto generated class, does this sound reasonable?
Thanks
All Replies
-
Tuesday, December 04, 2007 12:00 AMModerator
I am going to assume that in your CSDL EntityContainer, you have an EntitySet called "AnimalBase", and that it contains all entities of that type.
Since the properties that are generated on your context are not generated for each type, but for each EntitySet, you will only get a property generated for "AnimalBase".
Writing a partial class that does the query and selects from the AnimalBase set all instances of type Dog is an entirely reasonable thing to do.
As a bit of additional detail: The entity framework allows instances of an entity type to exist in multiple entity sets. This allows for some interesting mapping scenarios. What it does mean, though, is that when you ask the context for instances of a particular type, you have to specify, in some way, from which set you want those instances to come.
Some designer related detail: For now, the Entity Data Model Designer only allows one set per inheritance hierarchy, and that set is defined to contain all instances of the hierarchy's root type. This keeps the model and mapping UIs more manageable.
HTH,
Noam
-
Tuesday, December 04, 2007 2:32 AM
ah I wasn't aware that the properties generated on the context for each type was based on the entityset. But I was aware of the Multiple EntitySet stuff.
What I think I forgot to mention earlier was that I want te inherited entity type to appear in the context as a property so that I can use Linq to query it. In that case is it best for me to create an EntitySet for "Dog" (manually ofcourse)?
Thanks for you help.
-
Tuesday, December 04, 2007 7:15 PMModerator
It really depends on the kind of mapping and querying you want to do. The really is no reason, though, that you should not write a property in your partial class that returns an ObjectQuery<Dog> by querying the root entityset. Seems like the most natural way to go about it to me.
The implications of moving dog into its own entity set are:
- The designer will become quite unhappy with you and only open your edmx file, if you have one, in the XML editor
- Queries against the root type will not include instances of "Dog"
- Your mapping becomes complicated in sundry ways because you now cannot use an IsTypeOf mapping for your root type.
It seems like a lot to pay for just a property that you can query against.
. -
Wednesday, December 05, 2007 1:46 PM
ok so now i'm trying to do a Linq to Entity query on the subtype DOG and getting an error.
the query
Dim context As New TestModel.TestEntities'-- this works
Dim result2 = From a In context.AnimalBase _ Where a.ID = 33 _ Select aDebug.WriteLine(result2.First)
'-- this does NOT work
Dim result1 = From a In context.AnimalBase.OfType(Of TestModel.Dog)() _ Where a.ID = 33 _ Select aDebug.WriteLine(result1.First)
The one that does not work gives the error below. Any ideas please?
Error:
Message: Could not resolve type 'TestModel.NewsItem' in the given namespaces, near escaped identifier, line 5, column 1.
Source: System.Data.Entity
StackTrace:
at System.Data.Common.EntitySql.CqlErrorHelper.ReportTypeResolutionError(String[] names, ErrorContext errCtx, SemanticResolver sr)
at System.Data.Common.EntitySql.SemanticResolver.ResolveNameAsType(String[] names, ErrorContext errCtx)
at System.Data.Common.EntitySql.SemanticAnalyzer.ConvertTypeIdentifier(Expr typeIdentifierExpr, SemanticResolver sr)
at System.Data.Common.EntitySql.SemanticAnalyzer.<CreateBuiltInExprConverter>b__29(BuiltInExpr bltInExpr, SemanticResolver sr)
at System.Data.Common.EntitySql.SemanticAnalyzer.ConvertBuiltIn(Expr astExpr, SemanticResolver sr)
at System.Data.Common.EntitySql.SemanticAnalyzer.Convert(Expr astExpr, SemanticResolver sr)
at System.Data.Common.EntitySql.SemanticAnalyzer.ConvertGeneralExpression(Expr astExpr, SemanticResolver sr)
at System.Data.Common.EntitySql.SemanticAnalyzer.ConvertCommand(CommandExpr astCommandExpr, SemanticResolver sr)
at System.Data.Common.EntitySql.SemanticAnalyzer.Analyze(Expr astExpr)
at System.Data.Common.EntitySql.CqlQuery.AnalyzeSemantics(Expr astExpr, Perspective perspective, ParserOptions parserOptions, Dictionary`2 parameters, Dictionary`2 variables)
at System.Data.Common.EntitySql.CqlQuery.Compile(String query, Perspective perspective, ParserOptions parserOptions, Dictionary`2 parameters, Dictionary`2 variables, Boolean validateTree)
at System.Data.Objects.eSQLQueryImplementation`1.CreateCommandTree()
at System.Data.Objects.ELinq.ExpressionConverter.TranslateInlineQueryOfT(IObjectQueryOfT inlineQuery)
at System.Data.Objects.ELinq.ExpressionConverter.ConstantTranslator.TypedTranslate(ExpressionConverter parent, ConstantExpression linq)
at System.Data.Objects.ELinq.ExpressionConverter.TypedTranslator`1.Translate(ExpressionConverter parent, Expression linq)
at System.Data.Objects.ELinq.ExpressionConverter.TranslateExpression(Expression linq)
at System.Data.Objects.ELinq.ExpressionConverter.MethodCallTranslator.OneLambdaTranslator.Translate(ExpressionConverter parent, MethodCallExpression call, DbExpression& source, DbExpressionBinding& sourceBinding, DbExpression& lambda)
at System.Data.Objects.ELinq.ExpressionConverter.MethodCallTranslator.OneLambdaTranslator.Translate(ExpressionConverter parent, MethodCallExpression call)
at System.Data.Objects.ELinq.ExpressionConverter.MethodCallTranslator.SequenceMethodTranslator.Translate(ExpressionConverter parent, MethodCallExpression call, SequenceMethod sequenceMethod)
at System.Data.Objects.ELinq.ExpressionConverter.MethodCallTranslator.TypedTranslate(ExpressionConverter parent, MethodCallExpression linq)
at System.Data.Objects.ELinq.ExpressionConverter.TypedTranslator`1.Translate(ExpressionConverter parent, Expression linq)
at System.Data.Objects.ELinq.ExpressionConverter.TranslateExpression(Expression linq)
at System.Data.Objects.ELinq.ExpressionConverter.MethodCallTranslator.OneLambdaTranslator.Translate(ExpressionConverter parent, MethodCallExpression call, DbExpression& source, DbExpressionBinding& sourceBinding, DbExpression& lambda)
at System.Data.Objects.ELinq.ExpressionConverter.MethodCallTranslator.SelectTranslator.Translate(ExpressionConverter parent, MethodCallExpression call)
at System.Data.Objects.ELinq.ExpressionConverter.MethodCallTranslator.SequenceMethodTranslator.Translate(ExpressionConverter parent, MethodCallExpression call, SequenceMethod sequenceMethod)
at System.Data.Objects.ELinq.ExpressionConverter.MethodCallTranslator.TypedTranslate(ExpressionConverter parent, MethodCallExpression linq)
at System.Data.Objects.ELinq.ExpressionConverter.TypedTranslator`1.Translate(ExpressionConverter parent, Expression linq)
at System.Data.Objects.ELinq.ExpressionConverter.TranslateExpression(Expression linq)
at System.Data.Objects.ELinq.ExpressionConverter.Convert(Expression linq)
at System.Data.Objects.ELinq.ELinqQueryImplementation`1.BuildCommandTree()
at System.Data.Objects.ELinq.ELinqQueryImplementation`1.GetBaseCommandTree()
at System.Data.Objects.ELinq.ELinqQueryImplementation`1.Compile(MergeOption mergeOption)
at System.Data.Objects.Internal.ObjectQueryImplementation`1.GetResults(MergeOption mergeOption, Options materializerOptions)
at System.Data.Objects.Internal.ObjectQueryImplementation`1.GetResults(MergeOption mergeOption)
at System.Data.Objects.ObjectQuery`1.System.Collections.Generic.IEnumerable<T>.GetEnumerator()
at System.Linq.SystemCore_EnumerableDebugView`1.get_Items()
-
Wednesday, December 05, 2007 1:58 PM
ok so i'm not going mad. Apparently this is a bug according to this thread.
http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=2283501&SiteID=1
Cheers

