使用OData ODataModelBuilder注册IdentityUser和/或IdentityRole子类

时间:2014-08-28 20:42:37

标签: c# odata asp.net-identity

我在将Identity Framework的IdentityUser和IdentityRole与我的应用程序集成时遇到了一些问题。这就是我正在使用IdentityRole做的事情。

我在我的应用程序中将IdentityRole子类化为:

public partial class ActionRole : IdentityRole, IObjectState, ICanBeDisabledEntity, IAuditableEntity 
{
    ...
}

我试图使用ODataModelBuilder将'ActionRole'注册为实体集:

public static Microsoft.Data.Edm.IEdmModel GetModel()
    {
        ODataModelBuilder builder = new ODataConventionModelBuilder();
        ...
        builder.EntitySet<ActionRole>(typeof(ActionRole).Name);
        ...
        return builder.GetEdmModel();
    }

但是,当应用程序运行时,ODataConventionModelBuilder.GetEdmModel位于:

return builder.GetEdmModel(); 

方法调用返回以下异常:

System.InvalidOperationException: Sequence contains more than one element

我在System.Web.Http.OData库中查了一下,发现这是异常的来源:

internal void RemoveBaseTypeProperties(IEntityTypeConfiguration derivedEntity, IEntityTypeConfiguration baseEntity)
    {
        IEnumerable<IEntityTypeConfiguration> typesToLift = new[] { derivedEntity }.Concat(this.DerivedTypes(derivedEntity));

        foreach (PropertyConfiguration property in baseEntity.Properties.Concat(baseEntity.DerivedProperties()))
        {
            foreach (IEntityTypeConfiguration entity in typesToLift)
            {
                PropertyConfiguration derivedPropertyToRemove = entity.Properties.Where(p => p.Name == property.Name).SingleOrDefault();
                if (derivedPropertyToRemove != null)
                {
                    entity.RemoveProperty(derivedPropertyToRemove.PropertyInfo);
                }
            }
        }
    }

PropertyConfiguration derivedPropertyToRemove = entity.Properties.Where(p => p.Name == property.Name).SingleOrDefault();指向我的ActionRole实体,因为它有多个具有相同名称的属性,但我检查了它,似乎没有重复。

这是我的ActionRole类:

public class ActionRole : IdentityRole, IObjectState, ICanBeDisabledEntity, IAuditableEntity 
{

    private const String CacheKey = "somekey";

    [DisplayName("Rol")]
    [InversePropertyAttribute("ActionRole")]
    public virtual ICollection<Role> Role { get; set; }

    public static string GetCacheKey(String roleName)
    {
        return CacheKey + roleName;
    }

    public ObjectState ObjectState
    {
        get
        {
            throw new NotImplementedException();
        }
        set
        {
            throw new NotImplementedException();
        }
    }

    public bool IsDisabled
    {
        get
        {
            throw new NotImplementedException();
        }
        set
        {
            throw new NotImplementedException();
        }
    }

    public string CreateUser
    {
        get
        {
            throw new NotImplementedException();
        }
        set
        {
            throw new NotImplementedException();
        }
    }

    public DateTime CreateTime
    {
        get
        {
            throw new NotImplementedException();
        }
        set
        {
            throw new NotImplementedException();
        }
    }

    public string UpdateUser
    {
        get
        {
            throw new NotImplementedException();
        }
        set
        {
            throw new NotImplementedException();
        }
    }

    public DateTime UpdateTime
    {
        get
        {
            throw new NotImplementedException();
        }
        set
        {
            throw new NotImplementedException();
        }
    }
}

}

我很欣赏任何关于为什么会这样或者如何解决的见解。感谢。

1 个答案:

答案 0 :(得分:0)

事实证明,.NET Identity使用字符串ID作为其所有模型的默认标识符。因为我在模型中使用了int Id字段,所以这个语句的结果是多重匹配:

PropertyConfiguration derivedPropertyToRemove = entity.Properties.Where(p => p.Name == property.Name).SingleOrDefault();

即。两个具有相同名称但不同类型的属性。

我正在按照以下方式将所有模型切换为整数键:http://typecastexception.com/post/2014/07/13/ASPNET-Identity-20-Extending-Identity-Models-and-Using-Integer-Keys-Instead-of-Strings.aspx

我不太确定为什么.NET Identity Team决定使用该课程,但它对我的遗留应用程序进行了大量更改,我没有足够的资源来完成。

那个博客对我来说是一个救星。非常好的东西。