【发布时间】:2014-08-01 19:32:36
【问题描述】:
我开始使用 EF Code First 方法并自动生成数据库。现在我想添加另一个映射到 SQL 视图而不是表的实体。我正在使用视图,因为数据(员工信息)位于单独的数据库中。我添加了视图并创建了一个实体,但我不断收到上下文已更改的错误,我需要手动删除/更新数据库或调用 SetInitializer 方法。我认为问题在于我的模型定义或我对数据库更改的假设。
基本实体是 AppUser(应用程序特定用户)和 vEmp(查看员工数据)。 AppUser 实体不多:
public class AppUser
{
public AppUser()
{
}
[Key]
public int AppUserId { get; set; }
[MaxLength(75)]
public string ntUserDomainId { get; set; }
public bool isActive { get; set; }
public virtual vEmp vEmp { get; set; } // this was commented out at first to generate tables
}
vEmp 实体定义如下:
public class vEmp
{
[Key, ForeignKey("AppUser")]
public int AppUserId { get; set; }
public string empName { get; set; }
public string empStatus { get; set; }
public string orgid { get; set; }
public string email { get; set; }
public string ntUserDomainId { get; set; }
public virtual AppUser AppUser { get; set; }
}
为了完成这项工作,我在 AppUser 中注释掉了导航属性,以便 EF 生成表。然后我取消了导航属性的注释并遇到了错误。如果我尝试保留导航属性,则 EF 假定一个表并将“vEmp”创建为一个表。该视图实际上匹配用户 NT ID 以形成查询结果 - 我们使用 Windows 身份验证,因此每个用户在 AppUser 表中都有他们的 NT ID。
据我所知,[Key, ForeignKey("AppUser")] 行应该告诉 EF 如何管理关系。我唯一的猜测是 EF 希望创建一个交叉引用表以在两者之间进行映射。
我还想知道是否更简单的方法是先使用 DB 并使用 EF 从 DB 生成模型。我使用自动生成的 EDMX 使用类似的 vEmp entitye 和 AppUser 实体进行了一个测试项目,并且在我手动建立关联后似乎可以正常工作。我们有很多共享数据库,因此使用视图将很普遍,我想知道代码优先在这种情况下是否难以使用。
更新
我想我有证据证明 EF 想要创建一个表。我玩弄了迁移,这就是我所看到的:
public override void Up()
{
CreateTable(
"dbo.vEmps",
c => new
{
AppUserId = c.Int(nullable: false),
empName = c.String(),
empStatus = c.String(),
orgid = c.String(),
email = c.String(),
ntUserDomainId = c.String(),
})
.PrimaryKey(t => t.AppUserId)
.ForeignKey("dbo.AppUsers", t => t.AppUserId)
.Index(t => t.AppUserId);
}
如果我理解正确,EF 似乎看不到名为“vEmp”的 SQL 视图,而是想创建一个表。这是否意味着代码首先不适用于 SQL 视图?
更新 2 在多次尝试使代码优先语法工作失败后,我从数据库创建了一个 edmx 模型,因为它存在以测试 DB 优先进程。我添加了使用我的代码优先逻辑和我添加的 SQL 视图创建的所有表。然后我刚刚创建了一个与建模工具的关联,从表 AppUser 到视图 vEmp。建模工具似乎已创建此代码:
<Association Name="vEmpAppUser">
<End Type="JobControlModel.vEmp" Role="vEmp" Multiplicity="1" />
<End Type="JobControlModel.AppUser" Role="AppUser" Multiplicity="1" />
<ReferentialConstraint>
<Principal Role="AppUser">
<PropertyRef Name="AppUserId" />
</Principal>
<Dependent Role="vEmp">
<PropertyRef Name="AppUserId" />
</Dependent>
</ReferentialConstraint>
</Association>
其他一切(实体)看起来都一样。我使用控制台应用程序进行了快速测试,它似乎工作正常。
我不确定为什么这似乎适用于 DB 优先方法而不是代码优先方法。实体的定义相同。唯一的问题是尝试首先使用代码重新创建数据库首先调用的“关联”。
【问题讨论】:
标签: entity-framework ef-code-first