C# 每个类型继承的实体框架表-将继承的类型添加到数据库时出现错误“;无效的列名";

C# 每个类型继承的实体框架表-将继承的类型添加到数据库时出现错误“;无效的列名";,c#,asp.net-mvc,database,entity-framework,C#,Asp.net Mvc,Database,Entity Framework,这件事我已经做了一段时间了,我真的搞不懂。我使用的是EF5、MVC4、表/类型继承 我有从UserProfile继承的类租户和房东。注册用户时,选择他们想要的帐户类型,并且基于此选择,他们在表单上输入的详细信息(用户名、名字、姓氏、电子邮件、帐户类型、密码)应添加到UserProfile表中。然后,我希望将该表的PK作为外键添加到与他们选择的帐户类型(租户或房东)匹配的表中 我试图实现上述目标,但这导致了问题中描述的问题 我现在已经创建了一个RegisterTenantModel类,其属性映射到

这件事我已经做了一段时间了,我真的搞不懂。我使用的是EF5、MVC4、表/类型继承

我有从UserProfile继承的类租户和房东。注册用户时,选择他们想要的帐户类型,并且基于此选择,他们在表单上输入的详细信息(用户名、名字、姓氏、电子邮件、帐户类型、密码)应添加到UserProfile表中。然后,我希望将该表的PK作为外键添加到与他们选择的帐户类型(租户或房东)匹配的表中

我试图实现上述目标,但这导致了问题中描述的问题

我现在已经创建了一个RegisterTenantModel类,其属性映射到租户,我正在将RegisterTenantModel类型的对象传递给AccountController/Register,如下所示

// ...
if (tenantModel.AccountType == AccountType.Tenant)
                {
                    using (var db = new LetLordContext())
                    {
                        var t = db.UserProfile.Create<Tenant>();

                        WebSecurity.CreateUserAndAccount(tenantModel.UserName, tenantModel.Password,
                             t = new Tenant
                            {
                               AccountType = tenantModel.AccountType,
                               DateWantToRentFrom = DateTime.Now, 
                               DateWantToRentTo = DateTime.Now, 
                               DesiredPropertyLocation = "",
                               Email = tenantModel.Email, 
                               FirstName = tenantModel.FirstName,
                               UserId = WebSecurity.CurrentUserId, 
                               UserName = WebSecurity.CurrentUserName

                               // More properties that map to Tenant entity
                               // ...
                            },
                            false);

                        db.SaveChanges();
…因此,当我在
AccountController/Register
中调用
Websecurity.createuserandaccount()
时,它会根据
Websecurity.initializedabaseconnection()
中的参数写入UserProfile表。查看上面链接的问题,您将看到,根据表单上选择的帐户类型,租户或房东将通过调用

var tenant = db.UserProfile.Create<Tenant>();
//...
db.UserProfile.Add(tenant);
db.SaveChanges();
var-tenant=db.UserProfile.Create();
//...
db.UserProfile.Add(租户);
db.SaveChanges();
…导致将重复的条目添加到UserProfile表中


我认为解决方案是创建一个新表,并指向
WebSecurity.InitializeDatabaseConnection()

当我忘记在TPT中用表名注释子类时,我看到了这个错误

[Table("Tenant")]
public class Tenant : UserProfile { ...
能这么简单吗

编辑

快速搜索还建议将实体中的字段配对,然后一次将它们添加回一个字段中,以查看是否是单个字段造成的(它将提供一条错误消息,指示许多失败的列)。这听起来有点可疑,但可能值得一试:


您的WebSecurity.InitializeDatabaseConnection()方法调用是什么样子的?该调用标识用于存储用户数据的数据库表

CreateUserAndAccount()方法不使用上下文存储提供的数据,它只是将第三个调用参数的对象属性名称映射到InitializeDatabaseFile()方法中定义的表中的列

如果您不熟悉SimpleMembership机制,请阅读本文:

解决方案
  • 确保所有派生类都显式映射到表。两种简单的方法是:
  • TableAttribute
    class属性:
    [表(“租户”)]
  • ToTable
    Fluent API方法:
    ToTable(“租户”)
  • 确保基本类型为
    抽象类型
  • 确保您没有调用任何表的
    MapInheritedProperties
    配置方法。这种方法意味着TPC
  • 确保基本类型已注册为模型的一部分。两种简单的方法是:

  • 将访问者属性添加到
    DbContext
    的子类中:

    public DbSet<UserProfile> Users { get; set; }
    
  • 解释 如错误消息所示,实体框架似乎正在“派生”表中查找“基”表的列。这表明它试图使用“每具体类型表”(TPC)继承,而不是“每类型表”(TPT)

    让实体框架使用TPT是相当复杂的。如果你非常仔细地学习,你可能会发现你遗漏了什么,将所需配置总结如下:

    到目前为止,您已经看到,我们使用它的Requires方法来定制TPH。我们还使用了它的
    ToTable
    方法来创建TPT,现在我们使用它的
    MapInheritedProperties
    以及
    ToTable
    方法来创建TPC映射


    我的实验表明,上述总结过于简单。看起来,一个看似不相关的微小配置差异可能会导致使用意外的继承策略。

    我看到了完全相同的症状,这是因为我没有在
    DbContext
    上将基类声明为
    DbSet


    (与直觉相反,在我的应用程序中,我从不需要引用基类实体的集合,但现在就可以了。)

    不幸的是,租户类与上面一样。这事肯定有办法的?当然,他们不会在Mvc 4上附带一个依赖于Web安全性的用户配置文件模型,该模型无法扩展?添加了一个关于我发现的其他内容的更新,尽管我自己没有看到。我遇到了这个问题,但是当我在浏览器中看到错误页面时,它将所有字段都列为无效。我也进行了调试,正确的数据被传递到CreateUserAndAccount方法,它只是抛出了异常。注意,他得到的所有字段都是无效的,即使只有一个是问题所在。这听起来很可疑,但可能值得一试。我还将从删除DateTime内容开始。我不是在鼓吹这是一个好主意,只是一个想法:)你链接的问题似乎没有关系。这个问题似乎是EF试图使用TPC继承而不是TPT。该方法类似于WebSecurity。InitializeDatabaseConnection(“LetLordContext”、“UserProfile”、“UserId”、“UserName”,autoCreateTables:true);如果它不使用上下文来存储数据,是否有任何方法可以实现我想要的?我认为您的编辑是正确的。在我所有的成员身份实现中,我都将其配置为使用我的用户表,而不是特定于成员身份框架的默认成员身份/其他表。我不知道这是否是最佳实践,但如果不使用它
    public DbSet<UserProfile> Users { get; set; }
    
    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        base.OnModelCreating(modelBuilder);
        modelBuilder.Entity<UserProfile>();
    }