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

Horizontal inheritance with default mapping not working

5 Answers 76 Views
Data Access Free Edition
This is a migrated thread and some comments may be shown as answers.
This question is locked. New answers and comments are not allowed.
Joseph Lam
Top achievements
Rank 1
Joseph Lam asked on 21 Jul 2014, 10:48 PM
My model looks like this:

public abstract class EntityBase
{
    public int ID { get; set; } // intended to be the identity for each concrete class
}

public class MyEntity: EntityBase
{
    public string SomeField { get; set; }
}

My mapping code:

var entityBaseMapping = new MappingConfiguration<EntityBase>();
entityBaseMapping.MapType().Inheritance(InheritanceStrategy.Horizontal);

var myEntityMapping = new MappingConfiguration<MyEntity>();
myEntityMapping.MapType();
myEntityMapping.HasProperty(x => x.ID).IsIdentity();

Get this error when compiling:

Error 1 Type 'MyEntity' cannot access private identity field '<ID>k__BackingField' declared by type 'EntityBase'. The declaring type enhances this field as non-identity field.  Make sure to use a consistent mapping for both types or declare the field as protected.  Alternatively consider moving the identity field to the derived class. (OpenAccessEnhancedCopyKeyFieldsFromObjectId) 





5 Answers, 1 is accepted

Sort by
0
Kaloyan Nikolov
Telerik team
answered on 24 Jul 2014, 07:05 AM
Hi Joseph,

The reason is that the Telerik Data Access Enhancer tool is trying to access the filed of the ID property when processing the derived class. As the auto property generates a private filed it is not accessible from the derived class context. To solve this issue use a full property where the backing field is protected, like this:
public abstract class EntityBase
{
    protected int iD;
    public int ID
    {
        get
        {
            return this.iD;
        }
        set
        {
            this.iD = value;
        }
    } // intended to be the identity for each concrete class
}


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

Regards,
Kaloyan Nikolov
Telerik
 
OpenAccess ORM is now Telerik Data Access. For more information on the new names, please, check out the Telerik Product Map.
 
0
Joseph Lam
Top achievements
Rank 1
answered on 24 Jul 2014, 01:27 PM
Thanks. I think the example in the documentation missed this point:
http://docs.telerik.com/data-access/developers-guide/code-only-mapping/inheritance/fluent-mapping-inheritance-default-mapping

In the C# Animal class it should have used a protected backing field.
0
Joseph Lam
Top achievements
Rank 1
answered on 25 Jul 2014, 02:07 PM
Is there a way to configure the identity column once for the abstract base class so I don't have to repeat "myEntityMapping.HasProperty(x => x.ID).IsIdentity();" for all my entities?
0
Doroteya
Telerik team
answered on 28 Jul 2014, 12:49 PM
Hi Joseph,

Kindly find the answers you inquiries as follows:

1. Configuring the identity property in Horizontal inheritance
The general idea behind the horizontal inheritance structures is that the base class does not have a representation inside the database. With this in mind, and in order for the proper runtime behavior of Telerik Data Access, it is important that each of the child classes has its own configuration for the identity property regardless of the fact that in the conceptual model, it belongs to the base class.

2. Usage of protected backing fields in the documentation examples
Indeed, the example demonstrated in the mentioned article does not provide you with the implementation of the Animal class. I added a task for an update of the documentation with the relevant information, but at the time present I cannot provide you with a timeframe for it.

I hope this helps. If you need further information, do not hesitate to get back to us.



Regards,
Doroteya
Telerik
 
OpenAccess ORM is now Telerik Data Access. For more information on the new names, please, check out the Telerik Product Map.
 
0
Andrey
Top achievements
Rank 2
answered on 19 Jan 2016, 02:44 PM

This can be achieved without the use of inheritance

public partial class ModelMetadata : FluentMetadataSource
{
    protected override IList<MappingConfiguration> PrepareMapping()
    {
        List<MappingConfiguration> mappingConfigurations = new List<MappingConfiguration>();
 
        mappingConfigurations.Add(CreateBaseConfiguration<Positions>());
        mappingConfigurations.Add(CreateBaseConfiguration<Departament>());
  
        return mappingConfigurations;
    }
}
    

private MappingConfiguration<T> CreateBaseConfiguration<T>() where T : IPortalDataBase
{
    MappingConfiguration<T> baseConfig = new MappingConfiguration<T>();
    baseConfig.MapType().WithConcurencyControl(OptimisticConcurrencyControlStrategy.Version).UseDefaultMap();
    baseConfig.HasProperty(c => c.Id).IsIdentity(KeyGenerator.Guid).IsNotNullable();
    baseConfig.HasProperty(c => c.Timestamp).IsVersion();
    baseConfig.HasProperty(c => c.Create).IsCalculatedOn(DateTimeAutosetMode.Insert);
    baseConfig.HasProperty(c => c.Update).IsCalculatedOn(DateTimeAutosetMode.InsertAndUpdate);
    baseConfig.HasProperty(c => c.Status).HasDefaultValue();
    return baseConfig;
}

use interface

public interface IPortalDataBase
{
    Guid Id { get; set; }
    DateTime Create { get; set; }
    DateTime Update { get; set; }
    Int64 Timestamp { get; set; }
    DataStatus Status { get; set; }
}

The main drawback - the interface implementation. But it can just copy (or use the T4). But changing the interface implementation (a rare problem) and the class CreateBaseConfiguration we get a list of errors implementation of the interface in the other classes. Which just decide copying.

public class Departament : IPortalDataBase
{
    public Guid Id { get; set; }
    public DateTime Create { get; set; }
    public DateTime Update { get; set; }
    public Int64 Timestamp { get; set; }
    public DataStatus Status { get; set; }
 
    public string Name { get; set; }
}
 Too bad that you can not do the same properties in all classes automatically. Since the identifiers are usually the same, it is often used basic functions, such as versioning.It lacks some features, for example, instead of removing only marked as deleted, to preserve the history. But it is possible to realize the most hands.

Tags
Data Access Free Edition
Asked by
Joseph Lam
Top achievements
Rank 1
Answers by
Kaloyan Nikolov
Telerik team
Joseph Lam
Top achievements
Rank 1
Doroteya
Telerik team
Andrey
Top achievements
Rank 2
Share this question
or