locked
EF 5.x STE Generator for C# crashes when you create many to zero or one associations unchecking the zero or one navigation property RRS feed

  • Question

  • Hi:

    I have an error of Self-Tracking-Entity T4 template logic (EF 5.x STE Generator for C#) related to generated code within Many to Zero Or One relationship cases as follow:

    • Create new entity data model.
    • Add one entity (for example “Entity1”).
    • Add one association “many to zero or one” from “Entity1” to “Entity1” (to itself) with this characteristics:
      • Keep the navigation property to many (we can name it “NavigateToMany”).
      • Uncheck the navigation property to zero or one.
      • Uncheck “Add foreign key properties to the ‘Entity1’ Entity” option too.
    • Now add code generation item based on EF 5.x STE Generator for C#.
    • Run the templates and build the solution so you will note two errors each relating the same message:
      • “'SteRelationshipTroubles.Entity1' does not contain a definition for 'FixupModel_Entity1Entity1_Entity1Keys' and no extension method 'FixupModel_Entity1Entity1_Entity1Keys' accepting a first argument of type 'SteRelationshipTroubles.Entity1' could be found (are you missing a using directive or an assembly reference?)”

    I have been following the way of the template generation logic and it seems to be that the problem could be in line 546:

    “if (navProperty.ToEndMember.RelationshipMultiplicity != RelationshipMultiplicity.Many)”

    It seems to be that this line suppress the missing “FixupModel_Entity1Entity1_Entity1Keys” method generation.

    Please, skip from STE is not a choice, in fact I understand it created confusions to the community, but I think just to let it go and not to keep it was a Microsoft bad decision.

    Regards!


    Here is the .edmx content:

    <?xml version="1.0" encoding="utf-8"?>
    <edmx:Edmx Version="3.0" xmlns:edmx="http://schemas.microsoft.com/ado/2009/11/edmx">
      <!-- EF Runtime content -->
      <edmx:Runtime>
        <!-- SSDL content -->
        <edmx:StorageModels>
          <Schema xmlns="http://schemas.microsoft.com/ado/2009/11/edm/ssdl" Namespace="Model.Store" Alias="Self" Provider="System.Data.SqlClient" ProviderManifestToken="2005">
            <EntityContainer Name="ModelTargetContainer">
            </EntityContainer>
          </Schema>
        </edmx:StorageModels>
        <!-- CSDL content -->
        <edmx:ConceptualModels>
          <Schema xmlns="http://schemas.microsoft.com/ado/2009/11/edm" xmlns:cg="http://schemas.microsoft.com/ado/2006/04/codegeneration" xmlns:store="http://schemas.microsoft.com/ado/2007/12/edm/EntityStoreSchemaGenerator" Namespace="Model" Alias="Self" xmlns:annotation="http://schemas.microsoft.com/ado/2009/02/edm/annotation" annotation:UseStrongSpatialTypes="false">
            <EntityContainer Name="ModelContainer" annotation:LazyLoadingEnabled="true">
              <EntitySet Name="Entity1" EntityType="Model.Entity1" />
              <AssociationSet Name="Entity1Entity1" Association="Model.Entity1Entity1">
                <End Role="Entity1" EntitySet="Entity1" />
                <End Role="Entity11" EntitySet="Entity1" />
              </AssociationSet>
            </EntityContainer>
            <EntityType Name="Entity1">
              <Key>
                <PropertyRef Name="Id" />
              </Key>
              <Property Type="Int32" Name="Id" Nullable="false" annotation:StoreGeneratedPattern="Identity" />
              <NavigationProperty Name="NavigateToMany" Relationship="Model.Entity1Entity1" FromRole="Entity1" ToRole="Entity11" />
            </EntityType>
            <Association Name="Entity1Entity1">
              <End Type="Model.Entity1" Role="Entity1" Multiplicity="0..1" />
              <End Type="Model.Entity1" Role="Entity11" Multiplicity="*" />
            </Association>
          </Schema>
        </edmx:ConceptualModels>
        <!-- C-S mapping content -->
        <edmx:Mappings>
          <Mapping xmlns="http://schemas.microsoft.com/ado/2009/11/mapping/cs" Space="C-S">
            <Alias Key="Model" Value="Model" />
            <Alias Key="Target" Value="Model.Store" />
            <EntityContainerMapping CdmEntityContainer="ModelContainer" StorageEntityContainer="ModelTargetContainer">
            </EntityContainerMapping>
          </Mapping>
        </edmx:Mappings>
      </edmx:Runtime>
      <!-- EF Designer content (DO NOT EDIT MANUALLY BELOW HERE) -->
      <Designer xmlns="http://schemas.microsoft.com/ado/2009/11/edmx">
        <Connection>
          <DesignerInfoPropertySet>
            <DesignerProperty Name="MetadataArtifactProcessing" Value="EmbedInOutputAssembly" />
          </DesignerInfoPropertySet>
        </Connection>
        <Options>
          <DesignerInfoPropertySet>
            <DesignerProperty Name="ValidateOnBuild" Value="true" />
            <DesignerProperty Name="EnablePluralization" Value="True" />
            <DesignerProperty Name="CodeGenerationStrategy" Value="None" />
          </DesignerInfoPropertySet>
        </Options>
        <!-- Diagram content (shape and connector positions) -->
        <Diagrams>
        </Diagrams>
      </Designer>
    </edmx:Edmx>

    And here the generated code:

    [DataContract(IsReference = true)]
        [KnownType(typeof(Entity1))]
        public partial class Entity1: IObjectWithChangeTracker, INotifyPropertyChanged
        {
            #region Simple Properties
       
            [DataMember]
            public int Id
            {
                get { return _id; }
                set
                {
                    if (_id != value)
                    {
                        if (ChangeTracker.ChangeTrackingEnabled && ChangeTracker.State != ObjectState.Added)
                        {
                            throw new InvalidOperationException("The property 'Id' is part of the object's key and cannot be changed. Changes to key properties can only be made when the object is not being tracked or is in the Added state.");
                        }
                        _id = value;
                        OnPropertyChanged("Id");
                    }
                }
            }
            private int _id;

            #endregion

            #region Navigation Properties
       
            [DataMember]
            public TrackableCollection<Entity1> NavigateToMany
            {
                get
                {
                    if (_navigateToMany == null)
                    {
                        _navigateToMany = new TrackableCollection<Entity1>();
                        _navigateToMany.CollectionChanged += FixupNavigateToMany;
                    }
                    return _navigateToMany;
                }
                set
                {
                    if (!ReferenceEquals(_navigateToMany, value))
                    {
                        if (ChangeTracker.ChangeTrackingEnabled)
                        {
                            throw new InvalidOperationException("Cannot set the FixupChangeTrackingCollection when ChangeTracking is enabled");
                        }
                        if (_navigateToMany != null)
                        {
                            _navigateToMany.CollectionChanged -= FixupNavigateToMany;
                        }
                        _navigateToMany = value;
                        if (_navigateToMany != null)
                        {
                            _navigateToMany.CollectionChanged += FixupNavigateToMany;
                        }
                        OnNavigationPropertyChanged("NavigateToMany");
                    }
                }
            }
            private TrackableCollection<Entity1> _navigateToMany;

            #endregion

            #region ChangeTracking
       
            protected virtual void OnPropertyChanged(String propertyName)
            {
                if (ChangeTracker.State != ObjectState.Added && ChangeTracker.State != ObjectState.Deleted)
                {
                    ChangeTracker.State = ObjectState.Modified;
                }
                if (_propertyChanged != null)
                {
                    _propertyChanged(this, new PropertyChangedEventArgs(propertyName));
                }
            }
       
            protected virtual void OnNavigationPropertyChanged(String propertyName)
            {
                if (_propertyChanged != null)
                {
                    _propertyChanged(this, new PropertyChangedEventArgs(propertyName));
                }
            }
       
            event PropertyChangedEventHandler INotifyPropertyChanged.PropertyChanged{ add { _propertyChanged += value; } remove { _propertyChanged -= value; } }
            private event PropertyChangedEventHandler _propertyChanged;
            private ObjectChangeTracker _changeTracker;
       
            [DataMember]
            public ObjectChangeTracker ChangeTracker
            {
                get
                {
                    if (_changeTracker == null)
                    {
                        _changeTracker = new ObjectChangeTracker();
                        _changeTracker.ObjectStateChanging += HandleObjectStateChanging;
                    }
                    return _changeTracker;
                }
                set
                {
                    if(_changeTracker != null)
                    {
                        _changeTracker.ObjectStateChanging -= HandleObjectStateChanging;
                    }
                    _changeTracker = value;
                    if(_changeTracker != null)
                    {
                        _changeTracker.ObjectStateChanging += HandleObjectStateChanging;
                    }
                }
            }
       
            private void HandleObjectStateChanging(object sender, ObjectStateChangingEventArgs e)
            {
                if (e.NewState == ObjectState.Deleted)
                {
                    ClearNavigationProperties();
                }
            }
       
            protected bool IsDeserializing { get; private set; }
       
            [OnDeserializing]
            public void OnDeserializingMethod(StreamingContext context)
            {
                IsDeserializing = true;
            }
       
            [OnDeserialized]
            public void OnDeserializedMethod(StreamingContext context)
            {
                IsDeserializing = false;
                ChangeTracker.ChangeTrackingEnabled = true;
            }
       
            protected virtual void ClearNavigationProperties()
            {
                NavigateToMany.Clear();
            }

            #endregion

            #region Association Fixup
       
            private void FixupNavigateToMany(object sender, NotifyCollectionChangedEventArgs e)
            {
                if (IsDeserializing)
                {
                    return;
                }
       
                if (e.NewItems != null)
                {
                    foreach (Entity1 item in e.NewItems)
                    {
                        item.FixupModel_Entity1Entity1_Entity1Keys(this, false);
                        if (ChangeTracker.ChangeTrackingEnabled)
                        {
                            if (!item.ChangeTracker.ChangeTrackingEnabled)
                            {
                                item.StartTracking();
                            }
                            ChangeTracker.RecordAdditionToCollectionProperties("NavigateToMany", item);
                        }
                    }
                }
       
                if (e.OldItems != null)
                {
                    foreach (Entity1 item in e.OldItems)
                    {
                        item.FixupModel_Entity1Entity1_Entity1Keys(null, false);
                        if (ChangeTracker.ChangeTrackingEnabled)
                        {
                            ChangeTracker.RecordRemovalFromCollectionProperties("NavigateToMany", item);
                        }
                    }
                }
            }

            #endregion

        }

    • Edited by Jawilliam Thursday, February 28, 2013 7:55 PM
    Monday, February 18, 2013 8:43 PM

All replies

  • Hi Jawilliam,

    Welcome to the MSDN forum.

    I followed your steps on my machine with Visual Studio 2012 and .NET Framework 4.5. It works great without errors. Do you use Visual Studio 2012 and .NET Framework 4.5?

    Could you please try to recreate a solution and try the steps again to check whether error occurs or not?

    Best Regards,


    Alexander Sun [MSFT]
    MSDN Community Support | Feedback to us
    Develop and promote your apps in Windows Store
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.

    Wednesday, February 20, 2013 6:31 AM
  • Hi Alexander:

    I really have Visual Studio 2012 and .NET Frameworki 4.5, how could I recreate you my steps to ensure you are not losting any details of my way?

    Regards


    • Edited by Jawilliam Wednesday, February 20, 2013 10:50 PM
    Wednesday, February 20, 2013 10:49 PM
  • Here is the .edmx content:

    <?xml version="1.0" encoding="utf-8"?>
    <edmx:Edmx Version="3.0" xmlns:edmx="http://schemas.microsoft.com/ado/2009/11/edmx">
      <!-- EF Runtime content -->
      <edmx:Runtime>
        <!-- SSDL content -->
        <edmx:StorageModels>
          <Schema xmlns="http://schemas.microsoft.com/ado/2009/11/edm/ssdl" Namespace="Model.Store" Alias="Self" Provider="System.Data.SqlClient" ProviderManifestToken="2005">
            <EntityContainer Name="ModelTargetContainer">
            </EntityContainer>
          </Schema>
        </edmx:StorageModels>
        <!-- CSDL content -->
        <edmx:ConceptualModels>
          <Schema xmlns="http://schemas.microsoft.com/ado/2009/11/edm" xmlns:cg="http://schemas.microsoft.com/ado/2006/04/codegeneration" xmlns:store="http://schemas.microsoft.com/ado/2007/12/edm/EntityStoreSchemaGenerator" Namespace="Model" Alias="Self" xmlns:annotation="http://schemas.microsoft.com/ado/2009/02/edm/annotation" annotation:UseStrongSpatialTypes="false">
            <EntityContainer Name="ModelContainer" annotation:LazyLoadingEnabled="true">
              <EntitySet Name="Entity1" EntityType="Model.Entity1" />
              <AssociationSet Name="Entity1Entity1" Association="Model.Entity1Entity1">
                <End Role="Entity1" EntitySet="Entity1" />
                <End Role="Entity11" EntitySet="Entity1" />
              </AssociationSet>
            </EntityContainer>
            <EntityType Name="Entity1">
              <Key>
                <PropertyRef Name="Id" />
              </Key>
              <Property Type="Int32" Name="Id" Nullable="false" annotation:StoreGeneratedPattern="Identity" />
              <NavigationProperty Name="NavigateToMany" Relationship="Model.Entity1Entity1" FromRole="Entity1" ToRole="Entity11" />
            </EntityType>
            <Association Name="Entity1Entity1">
              <End Type="Model.Entity1" Role="Entity1" Multiplicity="0..1" />
              <End Type="Model.Entity1" Role="Entity11" Multiplicity="*" />
            </Association>
          </Schema>
        </edmx:ConceptualModels>
        <!-- C-S mapping content -->
        <edmx:Mappings>
          <Mapping xmlns="http://schemas.microsoft.com/ado/2009/11/mapping/cs" Space="C-S">
            <Alias Key="Model" Value="Model" />
            <Alias Key="Target" Value="Model.Store" />
            <EntityContainerMapping CdmEntityContainer="ModelContainer" StorageEntityContainer="ModelTargetContainer">
            </EntityContainerMapping>
          </Mapping>
        </edmx:Mappings>
      </edmx:Runtime>
      <!-- EF Designer content (DO NOT EDIT MANUALLY BELOW HERE) -->
      <Designer xmlns="http://schemas.microsoft.com/ado/2009/11/edmx">
        <Connection>
          <DesignerInfoPropertySet>
            <DesignerProperty Name="MetadataArtifactProcessing" Value="EmbedInOutputAssembly" />
          </DesignerInfoPropertySet>
        </Connection>
        <Options>
          <DesignerInfoPropertySet>
            <DesignerProperty Name="ValidateOnBuild" Value="true" />
            <DesignerProperty Name="EnablePluralization" Value="True" />
            <DesignerProperty Name="CodeGenerationStrategy" Value="None" />
          </DesignerInfoPropertySet>
        </Options>
        <!-- Diagram content (shape and connector positions) -->
        <Diagrams>
        </Diagrams>
      </Designer>
    </edmx:Edmx>

    And here the generated code:

    [DataContract(IsReference = true)]
        [KnownType(typeof(Entity1))]
        public partial class Entity1: IObjectWithChangeTracker, INotifyPropertyChanged
        {
            #region Simple Properties
       
            [DataMember]
            public int Id
            {
                get { return _id; }
                set
                {
                    if (_id != value)
                    {
                        if (ChangeTracker.ChangeTrackingEnabled && ChangeTracker.State != ObjectState.Added)
                        {
                            throw new InvalidOperationException("The property 'Id' is part of the object's key and cannot be changed. Changes to key properties can only be made when the object is not being tracked or is in the Added state.");
                        }
                        _id = value;
                        OnPropertyChanged("Id");
                    }
                }
            }
            private int _id;

            #endregion

            #region Navigation Properties
       
            [DataMember]
            public TrackableCollection<Entity1> NavigateToMany
            {
                get
                {
                    if (_navigateToMany == null)
                    {
                        _navigateToMany = new TrackableCollection<Entity1>();
                        _navigateToMany.CollectionChanged += FixupNavigateToMany;
                    }
                    return _navigateToMany;
                }
                set
                {
                    if (!ReferenceEquals(_navigateToMany, value))
                    {
                        if (ChangeTracker.ChangeTrackingEnabled)
                        {
                            throw new InvalidOperationException("Cannot set the FixupChangeTrackingCollection when ChangeTracking is enabled");
                        }
                        if (_navigateToMany != null)
                        {
                            _navigateToMany.CollectionChanged -= FixupNavigateToMany;
                        }
                        _navigateToMany = value;
                        if (_navigateToMany != null)
                        {
                            _navigateToMany.CollectionChanged += FixupNavigateToMany;
                        }
                        OnNavigationPropertyChanged("NavigateToMany");
                    }
                }
            }
            private TrackableCollection<Entity1> _navigateToMany;

            #endregion

            #region ChangeTracking
       
            protected virtual void OnPropertyChanged(String propertyName)
            {
                if (ChangeTracker.State != ObjectState.Added && ChangeTracker.State != ObjectState.Deleted)
                {
                    ChangeTracker.State = ObjectState.Modified;
                }
                if (_propertyChanged != null)
                {
                    _propertyChanged(this, new PropertyChangedEventArgs(propertyName));
                }
            }
       
            protected virtual void OnNavigationPropertyChanged(String propertyName)
            {
                if (_propertyChanged != null)
                {
                    _propertyChanged(this, new PropertyChangedEventArgs(propertyName));
                }
            }
       
            event PropertyChangedEventHandler INotifyPropertyChanged.PropertyChanged{ add { _propertyChanged += value; } remove { _propertyChanged -= value; } }
            private event PropertyChangedEventHandler _propertyChanged;
            private ObjectChangeTracker _changeTracker;
       
            [DataMember]
            public ObjectChangeTracker ChangeTracker
            {
                get
                {
                    if (_changeTracker == null)
                    {
                        _changeTracker = new ObjectChangeTracker();
                        _changeTracker.ObjectStateChanging += HandleObjectStateChanging;
                    }
                    return _changeTracker;
                }
                set
                {
                    if(_changeTracker != null)
                    {
                        _changeTracker.ObjectStateChanging -= HandleObjectStateChanging;
                    }
                    _changeTracker = value;
                    if(_changeTracker != null)
                    {
                        _changeTracker.ObjectStateChanging += HandleObjectStateChanging;
                    }
                }
            }
       
            private void HandleObjectStateChanging(object sender, ObjectStateChangingEventArgs e)
            {
                if (e.NewState == ObjectState.Deleted)
                {
                    ClearNavigationProperties();
                }
            }
       
            protected bool IsDeserializing { get; private set; }
       
            [OnDeserializing]
            public void OnDeserializingMethod(StreamingContext context)
            {
                IsDeserializing = true;
            }
       
            [OnDeserialized]
            public void OnDeserializedMethod(StreamingContext context)
            {
                IsDeserializing = false;
                ChangeTracker.ChangeTrackingEnabled = true;
            }
       
            protected virtual void ClearNavigationProperties()
            {
                NavigateToMany.Clear();
            }

            #endregion

            #region Association Fixup
       
            private void FixupNavigateToMany(object sender, NotifyCollectionChangedEventArgs e)
            {
                if (IsDeserializing)
                {
                    return;
                }
       
                if (e.NewItems != null)
                {
                    foreach (Entity1 item in e.NewItems)
                    {
                        item.FixupModel_Entity1Entity1_Entity1Keys(this, false);
                        if (ChangeTracker.ChangeTrackingEnabled)
                        {
                            if (!item.ChangeTracker.ChangeTrackingEnabled)
                            {
                                item.StartTracking();
                            }
                            ChangeTracker.RecordAdditionToCollectionProperties("NavigateToMany", item);
                        }
                    }
                }
       
                if (e.OldItems != null)
                {
                    foreach (Entity1 item in e.OldItems)
                    {
                        item.FixupModel_Entity1Entity1_Entity1Keys(null, false);
                        if (ChangeTracker.ChangeTrackingEnabled)
                        {
                            ChangeTracker.RecordRemovalFromCollectionProperties("NavigateToMany", item);
                        }
                    }
                }
            }

            #endregion

        }

    Friday, February 22, 2013 6:17 PM