使用实体框架的IdentityRole导航属性异常

时间:2015-01-07 19:32:56

标签: asp.net-mvc entity-framework

我遇到了映射" IdentityRole"的问题。属性到我的ApplicationUsers类。我收到的错误是:

++++

The declared type of navigation property WebApp.Core.DAL.ApplicationUsers.IdentityRoles is not     compatible with the result of the specified navigation.

Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code. 

Exception Details: System.Data.Entity.Core.MetadataException: The declared type of navigation property WebApp.Core.DAL.ApplicationUsers.IdentityRoles is not compatible with the result of the specified navigation. 

Source Error: 


Line 28:             using (CMSContext cntx = new CMSContext())
Line 29:             {
Line 30:                 var users = cntx.Users
Line 31:                                 .Include(m => m.IdentityRoles)
Line 32:                                 .Include(s => s.AspNetUsersSites)

Source File: c:\LocalSites\WebApp\1.0.0.0\DAL\UserManagement\User.cs    Line: 30 

Stack Trace: 


[MetadataException: The declared type of navigation property     WebApp.Core.DAL.ApplicationUsers.IdentityRoles is not compatible with the result of the specified navigation. ]
   System.Data.Entity.Core.Query.PlanCompiler.PreProcessor.ValidateNavPropertyOp(PropertyOp op) +401
   System.Data.Entity.Core.Query.PlanCompiler.PreProcessor.Visit(PropertyOp op, Node n) +80
   System.Data.Entity.Core.Query.PlanCompiler.SubqueryTrackingVisitor.VisitChildren(Node n) +163
   System.Data.Entity.Core.Query.PlanCompiler.PreProcessor.VisitScalarOpDefault(ScalarOp op, Node n) +33
   System.Data.Entity.Core.Query.PlanCompiler.SubqueryTrackingVisitor.VisitChildren(Node n) +163
   System.Data.Entity.Core.Query.InternalTrees.BasicOpVisitorOfNode.VisitDefault(Node n) +22
   System.Data.Entity.Core.Query.InternalTrees.BasicOpVisitorOfNode.VisitAncillaryOpDefault(AncillaryOp op, Node n) +21
   System.Data.Entity.Core.Query.PlanCompiler.SubqueryTrackingVisitor.VisitChildren(Node n) +163
   System.Data.Entity.Core.Query.InternalTrees.BasicOpVisitorOfNode.VisitDefault(Node n) +22
           System.Data.Entity.Core.Query.InternalTrees.BasicOpVisitorOfNode.VisitAncillaryOpDefault(AncillaryOp op, Node n) +21
   System.Data.Entity.Core.Query.PlanCompiler.SubqueryTrackingVisitor.VisitChildren(Node n) +163
   System.Data.Entity.Core.Query.PlanCompiler.SubqueryTrackingVisitor.VisitRelOpDefault(RelOp op, Node n) +38
   System.Data.Entity.Core.Query.PlanCompiler.PreProcessor.Visit(ProjectOp op, Node n) +599
   System.Data.Entity.Core.Query.PlanCompiler.SubqueryTrackingVisitor.VisitChildren(Node n) +163
   System.Data.Entity.Core.Query.InternalTrees.BasicOpVisitorOfNode.VisitDefault(Node n) +22
       System.Data.Entity.Core.Query.InternalTrees.BasicOpVisitorOfNode.VisitPhysicalOpDefault(PhysicalOp op, Node n) +21
   System.Data.Entity.Core.Query.PlanCompiler.PreProcessor.Process(Dictionary`2& tvfResultKeys) +106
   System.Data.Entity.Core.Query.PlanCompiler.PreProcessor.Process(PlanCompiler planCompilerState, StructuredTypeInfo& typeInfo, Dictionary`2& tvfResultKeys) +54
   System.Data.Entity.Core.Query.PlanCompiler.PlanCompiler.Compile(List`1& providerCommands, ColumnMap& resultColumnMap, Int32& columnCount, Set`1& entitySets) +236
   System.Data.Entity.Core.EntityClient.Internal.EntityCommandDefinition..ctor(DbProviderFactory storeProviderFactory, DbCommandTree commandTree, DbInterceptionContext interceptionContext, IDbDependencyResolver resolver, BridgeDataReaderFactory bridgeDataReaderFactory, ColumnMapFactory columnMapFactory) +441

++++

我有延迟加载,我的ApplicationUsers类看起来像这样

namespace WebApp.Core.Contracts
{
    public class ApplicationUsers : IdentityUser
    {
    public bool IsActive { get; set; }
    public string LockoutReason { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public string Photo { get; set; }

    public virtual List<AspNetUsersSites> AspNetUsersSites { get; set; }

    // a collection of roles that can be written to, since it needs to be evaluated earlier before it's disposed of
    [ForeignKey("Id")]
    public virtual List<IdentityRole> IdentityRoles { get; set; }

    public async Task<ClaimsIdentity> GenerateUserIdentityAsync(UserManager<ApplicationUsers> manager)
    {
        // Note the authenticationType must match the one defined in CookieAuthenticationOptions.AuthenticationType
        var userIdentity = await manager.CreateIdentityAsync(this, DefaultAuthenticationTypes.ApplicationCookie);
        // Add custom user claims here          
        return userIdentity;
    }

    public async Task<IList<string>> GenerateUserRolesAsync(UserManager<ApplicationUsers> manager, string userId)
    {
        var userRoles = await manager.GetRolesAsync(this.Id);
        return userRoles;
    }

    public async Task DeleteUser(UserManager<ApplicationUsers> manager, string username)
    {
        var user = manager.FindByName(username);            
        await manager.DeleteAsync(user);
    }                
}

我的Linq查询看起来像这样

 public static List<Contracts.ApplicationUsers> GetUsersForSiteWithRoles(int SiteID){
        using (CMSContext cntx = new CMSContext())
        {
            var users = cntx.Users
                            .Include(m => m.IdentityRoles)
                            .Include(s => s.AspNetUsersSites)
                            .Where(i => i.AspNetUsersSites.Where(s => s.SiteID == SiteID).Count() > 0).ToList();

            return users;
        }
    }

我添加的导航属性和/或查询有什么问题。我真正想做的就是返回用户的角色存储在我的数据库中。

谢谢!

1 个答案:

答案 0 :(得分:2)

首先,它应该是:

public virtual ICollection<IdentityRole> IdentityRoles { get; set; }

不是List<IdentityRole>

其次,通过ApplicationUser属性中IdentityUser的继承,Roles上已存在此关系。您正在此处创建一个永久不会被Identity框架使用的辅助关系。

另外,对于它的价值,如果您希望AspNetUserSites遵循Identity表的表名方案,则只需在类上指定Table属性。以这种方式命名你的课是迟钝的。例如:

[Table("AspNetUserSites")]
public class Site
{
    ...
}

然后你就有了一个很好的课程,比如Site,而不是AspNetUserSite

<强>更新

IdentityUserRole只是IdentityUserIdentityRole之间的联接表。在默认实现中,它的存在并不是很重要,但您可以扩展Identity类,以便以这种方式附加有关关系的其他信息。

无论如何,如果你只想获得实际的IdentityRoles,只需要做一些事情:

var roleIds = user.Roles.Select(r => r.RoleId).ToList();
var roleNames = db.Roles.Where(r => roleIds.Contains(r.Id)).Select(r => r.Name);