如何在实体之间建立关系& ApplicationUser在MVC 5 EF中

时间:2015-08-09 18:31:50

标签: c# asp.net-mvc entity-framework asp.net-mvc-5

如果我有一个SharedDocument实体,其中包含两个属性,我希望与我的ApplicationUser实体相关,我该怎么做?

在此MS Tutorial上,查看您是否将该属性命名为与要关联的表的PK相同,EF可以非常轻松地找到该关系。但我有两个属性CreatedBy&我想要的ModifiedBy与我的User表相关,但我不想将它们命名为AspNetUserId。我怎么能这样做?

模型

 public class SharedDocumentModel : DbContext
 {        
    public SharedDocumentModel()
        : base("MyContext")
    {

    }        

    public virtual DbSet<SharedDocument> PortalDocuments { get; set; }
 }

 public class SharedDocument
 {
    public int Id { get; set; }
    public string Name { get; set; }
    public DateTime Created { get; set; }
    public virtual ApplicationUser CreatedBy { get; set; }
    public DateTime Modified { get; set; }
    public virtual ApplicationUser ModifiedBy { get; set; }
    public string ContentType { get; set; }
    public string FileType { get; set; }
    public byte[] FileContent { get; set; }
    public double Version { get; set; }
 }
}

使用模型SharedDocuments创建视图时出错

There was an error running the selected code generator: 
'Unable to retrieve metadata for 
'MVC.WebSite.Models.SharedDocument'. One or more validation 
errors 'mere detected during model generation: 
MVC.WebSite.DAL.IdentityUserLogin: EntityType 'IdentityUserLogin' 
has no key defined. Define the key for this EntityType. 
MVC.WebSite.DAL.IdentityUserRoIe: EntityType 'IdentityUserRoIe' has 
no key defined. Define the key for this EntityType. 
IdentityUserLogins: EntityType: EntitySet 'IdentityUserLogins' is based 
on Vpe 'IdentityUserLogin' that has no keys defined. 
IdentityUserRoles: EntityType: EntitySet 'IdentityUserRoles' is based on 
type 'IdentityUserRole' that has no keys defined. 

3 个答案:

答案 0 :(得分:0)

您可以通过添加ForeignKey

来实现
[ForeignKey("CreatedById")]
[ForeignKey("ModifiedById")]

所以在你的情况下:

public class SharedDocument
{
    public int Id { get; set; }
    public string Name { get; set; }
    public DateTime Created { get; set; }
    [ForeignKey("CreatedById")]
    public virtual ApplicationUser CreatedBy { get; set; }
    public string CreatedById { get; set; }
    public DateTime Modified { get; set; }
    [ForeignKey("ModifiedById")]
    public virtual ApplicationUser ModifiedBy { get; set; }
    public string ModifiedById { get; set; }
    public string ContentType { get; set; }
    public string FileType { get; set; }
    public byte[] FileContent { get; set; }
    public double Version { get; set; }
}

还有一件事: 将DbContextApplicationDbContext合并,并使用一个数据库:

 public class ApplicationUser : IdentityUser
{
    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 class SharedDocumentModel : IdentityDbContext<ApplicationUser>
{
    public SharedDocumentModel()
        : base("DefaultConnection", throwIfV1Schema: false)
    {
    }
    public virtual DbSet<SharedDocument> PortalDocuments { get; set; }
    public static SharedDocumentModel Create()
    {
        return new SharedDocumentModel();
    }
}

答案 1 :(得分:0)

您的错误消息可能与引用ApplicationUser有关,因为它位于IdentityDbContext<ApplicationUser>上下文中。您可以将应用上下文设置为从IdentityDbContext<ApplicationUser>继承,否则您需要在SharedDocumentModel上下文中设置DbSet<ApplicationUser>的副本。

答案 2 :(得分:0)

您必须将FK的名称与属性名称匹配,而不是属性类型。因此,如果您拥有类型为User且名称为CreatedBy的媒体资源,则您的FK媒体资源必须为CreatedByID而不是UserID。因此,您只需将以下2个属性添加到SharedDocument类。

public class SharedDocument
{
    public string CreatedByID { get; set; }
    public virtual ApplicationUser CreatedBy { get; set; }

    public string ModifiedByID { get; set; }
    public virtual ApplicationUser ModifiedBy { get; set; }
    // rest of your code
}

正如您所看到的,FK属性的类型为string,因为ApplicationUser的PK类型也是string

但另一个重要问题是,您似乎正在使用Identity的默认配置。如果是这样,您的项目已经DbContext名为ApplicationDbContext。找到它并将其他实体添加到其中。不要实现新的DbContext

// This class already added to your project
public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
{
    public ApplicationDbContext()
        : base("DefaultConnection", throwIfV1Schema: false)
    {
    }

    // This context already had ApplicationUser set you don't need to add it again
    // add your own new entities 
    public DbSet<SharedDocument> PortalDocuments { get; set; }

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

最后请记住配置EF你有3个选项:

1)按惯例进行配置,如上所述。

2)按数据注释配置。通过向属性或clasees添加属性:

[ForeignKey("CreatedById")]
public virtual ApplicationUser CreatedBy { get; set; }

3)或者通过流畅的API:

public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
{
    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Entity<SharedDocument>()
            .HasRequired(e => e.CreatedBy)
            .WithMany()
            .Map(e => e.MapKey("CreatedByID"));

        modelBuilder.Entity<SharedDocument>()
            .HasRequired(e => e.ModifiedBy)
            .WithMany()
            .Map(e => e.MapKey("ModifiedByID"));
    }
    // rest of code same as before
}