Inheritance - Fluent API

6 posts, 0 answers
  1. Manuel
    Manuel avatar
    43 posts
    Member since:
    Jul 2010

    Posted 13 Mar 2014 Link to this post

    Hello,

    I made a base class for all my entities.

    public class EntityBase
    {
     private Guid id;
            [DataMember]
            public Guid Id
            {
                get { return id; }
                set
                {
                    if (Id != value)
                    {
                        id = value;
                        OnPropertyChanged();
                    }
                }
            }

            private string name;
            [DataMember]
            public virtual string Name
            {
                get { return name; }
                set
                {
                    if (Name != value)
                    {
                        name = value;
                        OnPropertyChanged();
                    }
                }
            }
    }

    Implementation works like this:
    public partial class Group : EntityBase
        {
            public Group()
            {
                Users = new List<User>();
            }

            public IList<User> Users { get; set; }
            }
         }

    In the MetaSource class I implemented the mapping:

     private void PrepareDefaultPropertyConfigurations<TEntity>(MappingConfiguration<TEntity> configuration)
                where TEntity : IEntityBase
            {
                configuration.HasProperty(x => x.Id).IsIdentity(KeyGenerator.Guid).IsNotNullable().HasColumnType("uniqueidentifier").HasPrecision(0).HasScale(0);
                configuration.HasProperty(x => x.Name).IsNullable().HasColumnType("nvarchar").HasLength(100);
            }

            public void PrepareGroupPropertyConfigurations(MappingConfiguration<Group> configuration)
            {
                configuration.HasProperty(x => x.Note).HasFieldName("_note").WithDataAccessKind(DataAccessKind.ReadWrite).ToColumn("Note").IsNullable().HasColumnType("nvarchar(max)").HasLength(0);

                PrepareDefaultPropertyConfigurations<Group>(configuration);
            }

    If I try to get the CreateUpdateDDlScript, I am getting the following error:

    Mapping for field 'name' is specified in the file 'config', but the field is not present in the class 'Tortuga.Data.Entities.Group'. --> FromMetadataContainer/namespace[Tortuga.Data.Entities]/class[Group]/field[name]

    How can I get the inheritance of mu base object working?
    Thank you,
    Manuell
  2. Kristian Nikolov
    Admin
    Kristian Nikolov avatar
    206 posts

    Posted 14 Mar 2014 Link to this post

    Hi Manuel,

    When using inheritance in your model, you need to specify the inheritance strategy in the mapping. Unless this is done, the fields for the inherited properties are expected to exist in the code file of the deriving class (while they are located in the base class). This causes the error you are experiencing.

    Telerik Data Access has a number of inheritance strategies more details for which you can read in this documentation section. As in your scenario it appears that the base class will not be used on its own, I will show you an example of mapping Horizontal inheritance. This type of inheritance strategy is specified only for the mapping configuration of the base class. Additionally, identity members are defined only for the deriving classes. The following snippet is an example based on the code you provided:
    protected override IList<MappingConfiguration> PrepareMapping()
    {
        List<MappingConfiguration> mappingConfigurations = new List<MappingConfiguration>();
     
        mappingConfigurations.Add(this.PrepareBaseMappingConfig());
        mappingConfigurations.Add(this.PrepareGroupMappingConfig());
     
        return mappingConfigurations;
    }
     
    private MappingConfiguration<EntityBase> PrepareBaseMappingConfig()
    {
        MappingConfiguration<EntityBase> baseConfig = new MappingConfiguration<EntityBase>();
        //the base clas is not mapped to a table as we are using horizontal inheritance
        baseConfig.MapType().Inheritance(InheritanceStrategy.Horizontal);
        return baseConfig;
    }
     
    private MappingConfiguration<Group> PrepareGroupMappingConfig()
    {
        MappingConfiguration<Group> groupConfig = new MappingConfiguration<Group>();
        groupConfig.MapType().ToTable("Groups");
        groupConfig.FieldNamingRules.AddPrefix = "_";
        groupConfig.HasProperty(group => group.Id).IsIdentity(KeyGenerator.Guid).IsNotNullable().HasColumnType("uniqueidentifier").HasPrecision(0).HasScale(0);
        groupConfig.HasProperty(group => group.Name).IsNullable().HasColumnType("nvarchar").HasLength(100);
        groupConfig.HasProperty(group => group.Note).WithDataAccessKind(DataAccessKind.ReadWrite).ToColumn("Note").IsNullable().HasColumnType("nvarchar").WithInfiniteLength();
     
        return groupConfig;
    }

    As a result, in your database you would have a table with columns for the properties both inherited and defined in the Group class.

    I hope this helps. Should you have additional questions, do not hesitate to get back to us.

    Regards,
    Kristian Nikolov
    Telerik
     
    OpenAccess ORM is now Telerik Data Access. For more information on the new names, please, check out the Telerik Product Map.
     
  3. DevCraft banner
  4. Mathias
    Mathias avatar
    1 posts
    Member since:
    Feb 2012

    Posted 05 Feb 2015 Link to this post

    I am having a similar problem with inheritance from an abstract class.

    So as an example similar to the previous post:

    public interface IEntity
    {
        Guid Id { get; }
    }
     
    public abstract class EntityBase : IEntity
    {
        public Guid Id { get; set; }
    }
     
    public class Product : EntityBase
    {
        public string Name { get; set; }
        public DateTime Released { get; set; }
    }

    And the mapping

    public class MyFluentMetadataSource : FluentMetadataSource
            {
     
                protected override IList<MappingConfiguration> PrepareMapping()
                {
     
                    List<MappingConfiguration> list = new List<MappingConfiguration>();
     
                    MappingConfiguration<EntityBase> entityConfiguration = new MappingConfiguration<EntityBase>();
                    entityConfiguration.MapType().Inheritance(InheritanceStrategy.Horizontal);
                     
     
                    MappingConfiguration<Product> productConfiguration = new MappingConfiguration<Product>();
                    productConfiguration.MapType().ToTable("Product");
     
                    productConfiguration.HasProperty(p => p.Id).IsIdentity(KeyGenerator.Guid).IsNotNullable().HasColumnType("uniqueidentifier").HasPrecision(0).HasScale(0);
                    productConfiguration.HasProperty(p => p.Name).IsNullable().HasColumnType("nvarchar").HasLength(100);
                    productConfiguration.HasProperty(p => p.Released).IsNullable().HasColumnType("datetime");
     
                    list.Add(entityConfiguration);
                    list.Add(productConfiguration);
     
                    return list;
     
                }
     
            }

    which gives me the error:




    Telerik.OpenAccess.Exceptions.MetadataException was unhandled
      HResult=-2146233088
      Message=Mapping for class 'WorkflowTestConsole.EntityBase' is specified in file 'config' but the class could not be found. --> FromMetadataContainer/namespace[WorkflowTestConsole]/class[EntityBase]
      Source=Telerik.OpenAccess
      CanRetry=true

    Not sure what it is Im doing wrong

    Any help would be appreciated.
  5. Kristian Nikolov
    Admin
    Kristian Nikolov avatar
    206 posts

    Posted 10 Feb 2015 Link to this post

    Hi Mathias,

    Thank you for contacting us.

    Using the provided MetadataSource, classes and interface we attempted to reproduce the behavior you are experiencing. Using the resulting model we were able to successfully create a database, and insert new Product records in it. We were unable to reproduce the error. Therefore we would need some additional information in order to further investigate the situation:
    1. Are all of the components of your model (interfaces, classes, MetadataSource, Context) located in the same project?
    2. Are you getting the error at runtime, or when you attempt to build the project?
    3. If you are getting the exception at runtime, what is the code that throws it?
    4. Is the Enhancer tool integrated in to the project which holds your model via the following line in the MsBuild script:
      <Import Condition="Exists('$(MSBuildExtensionsPath)\OpenAccess.targets')" Project="$(MSBuildExtensionsPath)\OpenAccess.targets" />
    We are looking forward to your feedback.

    Regards,
    Kristian Nikolov
    Telerik
     
    OpenAccess ORM is now Telerik Data Access. For more information on the new names, please, check out the Telerik Product Map.
     
  6. Manuel
    Manuel avatar
    43 posts
    Member since:
    Jul 2010

    Posted 28 Jul 2015 in reply to Kristian Nikolov Link to this post

    Dear Kristian,

     

    today I updated to the latest version of the Fluents API. The version of  Telerik OpenAccess is: 2015.2.624.1

     

    Now I am getting this error:

    No metadata has been registered for class 'EntityBase​'

    This usually indicates, that either this class is not declared persistent or it is declared persistent but not enhanced.

     

    With the old Version (2015 Q1) it is working.

    I used VS 2013 & FW 4.5.2.

     

    Thank you,

    Manuel

  7. Doroteya
    Admin
    Doroteya avatar
    502 posts

    Posted 31 Jul 2015 Link to this post

    Hi Manuel,

    It seems that the subject of your latest post is the same as the one discussed in support thread #957370.

    If so, the reason for the error on your side is that the Tortuga.Data.Dal project file does not contain the clause that calls the Enhancer tool. The suggested solution is to reinstall the Telerik.DataAccess.Fluent NuGet package.

    If you need further information or my assumption is not correct, let me know.


    Regards,
    Doroteya
    Telerik
     
    Check out the latest announcement about Telerik Data Access vNext as a powerful framework able to solve core development problems.
Back to Top
DevCraft banner