C# ApplicationUser不是当前上下文的模型的一部分

C# ApplicationUser不是当前上下文的模型的一部分,c#,entity-framework,asp.net-mvc-4,asp.net-identity,dbcontext,C#,Entity Framework,Asp.net Mvc 4,Asp.net Identity,Dbcontext,我有一个同事给我的ASP MVC项目,它有两个上下文。一个来自登录所需的模板,另一个是自制的。所以我想将两者结合起来,但我一直都会遇到这个错误: ApplicationUser is not part of the model for the current context 模型首先是数据库。我首先创建了SQL表,然后创建了一个ADO.NET实体数据模型,该模型提供了以下连接字符串: <add name="DairyCowBarnEntities" connectionString="m

我有一个同事给我的ASP MVC项目,它有两个上下文。一个来自登录所需的模板,另一个是自制的。所以我想将两者结合起来,但我一直都会遇到这个错误:

ApplicationUser is not part of the model for the current context
模型首先是数据库。我首先创建了SQL表,然后创建了一个ADO.NET实体数据模型,该模型提供了以下连接字符串:

<add name="DairyCowBarnEntities" connectionString="metadata=res://*/Models.DairyCowBarnModel.csdl|res://*/Models.DairyCowBarnModel.ssdl|res://*/Models.DairyCowBarnModel.msl;provider=System.Data.SqlClient;provider connection string=&quot;data source=server;initial catalog=DairyCowBarn;integrated security=True;MultipleActiveResultSets=True;App=EntityFramework&quot;" providerName="System.Data.EntityClient" />

我不知道怎样才能把两者结合起来。我没有主意了。任何帮助都是非常感激和需要的。希望我能解释清楚。否则,只需询问是否需要更多信息。

当您对数据库进行反向工程时,它会拉入您不需要的AspNet表。关于身份验证,您需要的唯一模型是

public class ApplicationUser : IdentityUser
{
    public DateTimeOffset CreatedOn { get; set; }

    public async Task<ClaimsIdentity> GenerateUserIdentityAsync(UserManager<ApplicationUser> 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;
    }
}
公共类应用程序用户:IdentityUser
{
public DateTimeOffset CreatedOn{get;set;}
公共异步任务GenerateUserIdentityAsync(用户管理器)
{
//注意authenticationType必须与CookieAuthenticationOptions.authenticationType中定义的类型匹配
var userIdentity=wait manager.CreateIdentityAsync(这是DefaultAuthenticationTypes.ApplicationOkie);
//在此处添加自定义用户声明
返回用户身份;
}
}
我已经在我的AspNetUsers表中添加了CreatedOn列,这就是为什么它在上面的模型中。下一步是确保DbContext来自
IdentityDbContext
。这个基类将处理到AspNet表的映射。因此,您的DbContext应该如下所示:

public partial class DairyCowBarnEntities : IdentityDbContext<ApplicationUser>
{
    public DairyCowBarnEntities()
        : base("name=DairyCowBarnEntities")
    {
    }

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        throw new UnintentionalCodeFirstException();
    }

    public static DairyCowBarnEntities Create()
    {
        return new DairyCowBarnEntities();
    }

    public virtual DbSet<jntConcentrateMixture> jntConcentrateMixtures { get; set; }
    public virtual DbSet<jntConsistingParcel> jntConsistingParcels { get; set; }

}
公共部分类DairyCowBarnEntities:IdentityDbContext
{
公共奶牛场()
:base(“name=DairyCowBarnEntities”)
{
}
模型创建时受保护的覆盖无效(DbModelBuilder modelBuilder)
{
抛出新代码FirstException();
}
公共静态DairyCowBarnEntities创建()
{
返回新的DairyCowBarnEntities();
}
公共虚拟DbSet jntconcentratemilxes{get;set;}
公共虚拟数据库集jntConsistingParcels{get;set;}
}
所以,要这样做,就要删除与AspNet有关的所有模型以及代码中对这些模型的所有引用。添加ApplicationUser模型,但不要为其创建数据库集并将其传递到派生类
IdentityDbContext
。IdentityDbContext将处理有关身份验证和授权的所有信息,因此您可以正常使用UserManager和Identity

请注意,my CreatedOn是使用默认值(sysdatetimeoffset())生成的数据库,但它从未工作过。我必须在代码中显式设置CreatedOn,或者将其填充到数据库中作为DateTimeOffset.MinValue

更新以回答评论:

数据库上下文从中派生的
IdentityDbContext
为您处理该映射。它提供了一个抽象层,因此您不必担心它。如果您需要查询那些超出UserManager将为您做的工作的表,即;在获取所有未确认的用户电子邮件地址时,您始终可以编写自己的select语句并将其传递到dbContext中,如
dbContext.Database.SqlQuery(SqlQuery,false)T将是您创建的一个模型,该模型的属性名称和类型应与您正在查询的列名相同。下面的例子

公共用户
{
公共字符串用户名{get;set;}
公共布尔值{get;set;}
}
var sqlQuery=“选择Users.UserName,Users.emailconfirm FROM AspNetUsers WHERE Users.emailconfirm={0}”
var unconfirmedUsers=dbContext.Database.SqlQuery(SqlQuery,false).ToList();

使用
{0}
并将该值作为参数传递将自动删除该值,因此sql注入脚本将无法工作。

我不明白为什么要删除AspNet表?那么我如何存储用户帐户信息和角色呢?我编辑了上面的答案来回答您的问题。至于存储用户帐户信息和角色,您应该了解UserManager和添加ApplicationUser。如果您启动一个新的MVC应用程序,您可以看到他们是如何使用它来管理用户的。@JacobRoberts关于引用呢?我想从数据库上下文中的其他实体引用我的身份相关实体。比如,如果我有一个
LocationUser
表,它将
Locations
表链接到我的
AspNetUsers
表,会怎么样?我想使用EF执行类似于
Dim localUsers=db.Locations(“some id”).AspNetUsers.ToList()的操作,以获取属于该位置的用户。
The context is being used in Code First mode with code that was generated from an EDMX file for either Database First or Model First development.  This will not work correctly. To fix this problem do not remove the line of code that throws this exception. If you wish to use Database First or Model First, then make sure that the Entity Framework connection string is included in the app.config or web.config of the start-up project. If you are creating your own DbConnection, then make sure that it is an EntityConnection and not some other type of DbConnection, and that you pass it to one of the base DbContext constructors that take a DbConnection.
public class ApplicationUser : IdentityUser
{
    public DateTimeOffset CreatedOn { get; set; }

    public async Task<ClaimsIdentity> GenerateUserIdentityAsync(UserManager<ApplicationUser> 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 partial class DairyCowBarnEntities : IdentityDbContext<ApplicationUser>
{
    public DairyCowBarnEntities()
        : base("name=DairyCowBarnEntities")
    {
    }

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        throw new UnintentionalCodeFirstException();
    }

    public static DairyCowBarnEntities Create()
    {
        return new DairyCowBarnEntities();
    }

    public virtual DbSet<jntConcentrateMixture> jntConcentrateMixtures { get; set; }
    public virtual DbSet<jntConsistingParcel> jntConsistingParcels { get; set; }

}
public Users
{
    public string UserName { get; set; }
    public bool EmailConfirmed { get; set; }
}

var sqlQuery = "SELECT Users.UserName, Users.EmailConfirmed FROM AspNetUsers WHERE Users.EmailConfirmed = {0}"
var unconfirmedUsers = dbContext.Database.SqlQuery<Users>(sqlQuery, false).ToList();