This is a migrated thread and some comments may be shown as answers.

Inheritance - Fluent API

5 Answers 101 Views
Development (API, general questions)
This is a migrated thread and some comments may be shown as answers.
This question is locked. New answers and comments are not allowed.
Manuel
Top achievements
Rank 1
Manuel asked on 13 Mar 2014, 01:01 PM
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

5 Answers, 1 is accepted

Sort by
0
Kristian Nikolov
Telerik team
answered on 14 Mar 2014, 05:05 PM
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.
 
0
Mathias
Top achievements
Rank 1
answered on 05 Feb 2015, 04:23 PM
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.
0
Kristian Nikolov
Telerik team
answered on 10 Feb 2015, 11:13 AM
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.
 
0
Manuel
Top achievements
Rank 1
answered on 28 Jul 2015, 04:09 PM

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

0
Doroteya
Telerik team
answered on 31 Jul 2015, 08:56 AM
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.
Tags
Development (API, general questions)
Asked by
Manuel
Top achievements
Rank 1
Answers by
Kristian Nikolov
Telerik team
Mathias
Top achievements
Rank 1
Manuel
Top achievements
Rank 1
Doroteya
Telerik team
Share this question
or