Search code examples
entity-frameworkodataasp.net-identity

Duplicate columns in odata metadata


I am trying to export Asp.Net Identity classes in the OData metadata. Now the the IdentityUserLogin class contains three primary keys which are not marked with [Key] attribute. When the metadata is generated, the key definition is missing in the output

<EntityType Name="IdentityUserLogin">
  <Property Name="LoginProvider" Type="Edm.String"/>
  <Property Name="ProviderKey" Type="Edm.String"/>
  <Property Name="UserId" Type="Edm.String"/>
</EntityType>

Normally, to fix this all I need to do is add the keys manully using HasKey method like so

ODataConventionModelBuilder builder = new ODataConventionModelBuilder();

builder.EntitySet<IdentityUserLogin>("Logins").EntityType
  .HasKey(l => new { l.LoginProvider, l.ProviderKey, l.UserId });

var EDM = builder.GetEdmModel();

config.Routes.MapODataServiceRoute("odata", "api", EDM, 
  new DefaultODataBatchHandler(GlobalConfiguration.DefaultServer));

while the above generates the key definition for the entity, it also creates duplicate columns

<EntityType Name="IdentityUserLogin">
  <Key>
    <PropertyRef Name="LoginProvider"/>
    <PropertyRef Name="ProviderKey"/>
    <PropertyRef Name="UserId"/>
  </Key>
  <Property Name="LoginProvider" Type="Edm.String" Nullable="false"/>
  <Property Name="ProviderKey" Type="Edm.String" Nullable="false"/>
  <Property Name="UserId" Type="Edm.String" Nullable="false"/>
  <Property Name="LoginProvider" Type="Edm.String"/>
  <Property Name="ProviderKey" Type="Edm.String"/>
  <Property Name="UserId" Type="Edm.String"/>
</EntityType>

Am I doing something wrong here ? Note that this also happens with IdentityUserRole class.


Solution

  • There is a way to avoid the bug mentioned here and here, if one derives the identity types - e.g. in order to have different type of keys. Since I derive all identity types and the relevant properties are virtual, I am able to override the key properties an set the [Key] attribute. Thus I don't need to explicitly define the keys and thus can avoid the duplicate-property-bug.

    public class UserLogin : MultitenantIdentityUserLogin<Guid, Guid>
    {
        [Key]
        public override Guid TenantId
        {
            get { return base.TenantId; }
            set { base.TenantId = value; }
        }
    
        [Key]
        public override string LoginProvider
        {
            get { return base.LoginProvider; }
            set { base.LoginProvider = value; }
        }
    
        [Key]
        public override string ProviderKey
        {
            get { return base.ProviderKey; }
            set { base.ProviderKey = value; }
        }
    
        [Key]
        public override Guid UserId
        {
            get { return base.UserId; }
            set { base.UserId = value; }
        }
    }
    
    public class UserRole : IdentityUserRole<Guid>
    {
        [Key]
        public override Guid UserId
        {
            get { return base.UserId; }
            set { base.UserId = value; }
        }
    
        [Key]
        public override Guid RoleId
        {
            get { return base.RoleId; }
            set { base.RoleId = value; }
        }    
    }
    
    public class UserClaim : IdentityUserClaim<Guid>
    {
        [Key]
        public override int Id
        {
            get { return base.Id; } 
            set { base.Id = value; }
        }
    }
    

    Regards, Kasimier Buchcik