Note: Forums will be making significant UX changes to address key usability improvements surrounding search, discoverability and navigation. To learn more about these changes please visit the announcement which can be found HERE.

Answered 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 ArticlesBaseDATA

    Inherits 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 Dog

    dog.ID = iD

    Return dog

    End Function

    End Class

     

    In 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 AM
    Moderator
     
     

    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 PM
    Moderator
     
     

    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. Smile.

  • 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 a

    Debug.WriteLine(result2.First)

     

    '-- this does NOT work

    Dim result1 = From a In context.AnimalBase.OfType(Of TestModel.Dog)() _

    Where a.ID = 33 _

    Select a

    Debug.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
     
     Answered

     

    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