Configuration 实体框架Fluent API在相关对象的sql中生成额外列
我有一个预先存在的数据模型,最初使用EF4访问。更新到EF 6,遇到配置语法更改的问题,并正确定义要查询的关系 在这个特定的例子中,我的外键关系在SQL中生成两列,一列是我定义的,另一列是不知从何而来的 我有以下两个对象-Company和AppUser:Configuration 实体框架Fluent API在相关对象的sql中生成额外列,configuration,entity-framework-6,ef-fluent-api,Configuration,Entity Framework 6,Ef Fluent Api,我有一个预先存在的数据模型,最初使用EF4访问。更新到EF 6,遇到配置语法更改的问题,并正确定义要查询的关系 在这个特定的例子中,我的外键关系在SQL中生成两列,一列是我定义的,另一列是不知从何而来的 我有以下两个对象-Company和AppUser: public class Company : EntityBase, IComparable<Company> { public string Name { get; set; } public virtual IL
public class Company : EntityBase, IComparable<Company>
{
public string Name { get; set; }
public virtual IList<AppSystem> AppSystems { get; set; }
public virtual IList<AppUser> AppUsers { get; set; }
public string PortalCustomerName { get; set; }
}
public class AppUser : EntityBase
{
public string FirstName { get; set; }
public string LastName { get; set; }
public string Email { get; set; }
public virtual Company Company { get; set; }
public FlowStatus FlowStatus { get; set; }
public virtual IList<AppUserRole> AppUserRoles { get; set; }
}
public abstract class EntityBase
{
/// <summary>
/// The id assigned by the system.
/// </summary>
public virtual int Id { get; set; }
}
然而,当我查询AppUsers时,我遇到了查询问题。通过上面的配置,我获得了对CompanyId的正确请求,但我还获得了一个额外的列Company_Id1:
SELECT
[Extent1].[AppUserId] AS [AppUserId],
[Extent1].[FirstName] AS [FirstName],
[Extent1].[LastName] AS [LastName],
[Extent1].[Email] AS [Email],
[Extent1].[FlowStatus] AS [FlowStatus],
[Extent1].[CompanyID] AS [CompanyID],
**[Extent1].[Company_Id1] AS [Company_Id1]**
FROM [dbo].[AppUser] AS [Extent1]
WHERE ([Extent1].[AppUserId] > 0) AND (N'Joe' = [Extent1].[LastName])
但是如果我删除映射并用“HasMany()”结束配置,正确的映射就会消失,Company_Id1就会变成“Company_Id”:
我的配置有什么问题?使用
EntityTypeConfiguration
的主要缺陷是配置关系。问题在于,关系通常涉及两个实体,但只需要(正确地)配置一次。配置必须准确反映当前的导航和FK属性
在您的情况下,您有两个相同关系的配置:
公司:
应用程序用户:
注意第二个配置中的无参数和多个
根据经验,始终在一个位置配置关系。由于Has
方法需要导航属性,而With
方法不需要导航属性,因此请在具有导航属性的实体的配置中执行此操作。如果两个实体都具有关系的导航属性,则使用其中一个(但仍然只执行一次)
应用于您的场景,因为您的两个实体都有导航属性,请从Company
配置中删除现有行,并在AppUser
配置中使用以下命令:
HasRequired(u => u.Company).WithMany(c => c.AppUsers).Map(m => m.MapKey("CompanyID"));
HasMany(c => c.AppUsers).WithRequired(u => u.Company).Map(m => m.MapKey("CompanyID"));
或者从AppUser
配置中删除现有行,并在公司
配置中使用以下内容:
HasRequired(u => u.Company).WithMany(c => c.AppUsers).Map(m => m.MapKey("CompanyID"));
HasMany(c => c.AppUsers).WithRequired(u => u.Company).Map(m => m.MapKey("CompanyID"));
看来是我自己解决的。我将公司配置修改为:
HasMany(c => c.AppUsers).WithRequired(u=>u.Company).Map(u=>u.MapKey("CompanyId"));
并更改了AppUserConfiguration
HasRequired(u => u.Company);
显然,通过将映射定义移动到主要对象(Company),我告诉EF-Company可以被许多用户使用,用户必须有一个Company,并将其标识为“CompanyId”
谢谢你的详细解释——正如你所看到的,我解决了这个问题,但我不清楚为什么。你的解释澄清了-我只需要在一个地方定义关系。按照这种想法,我从AppUserConfiguration中完全删除了对Company的引用,并将定义保留在Company中,得到了相同的SQL。也就是说,你有没有想过应该在哪里定义关系?我认为,在“子”(用户)依赖于“母公司”(公司)的情况下,关系最好在“子公司”中定义。WRT导航-在这种情况下,如果我们在实体之间导航,它将从用户导航到公司,因此进一步强调,至少在这种情况下,关系定义属于用户(以及最终的AppSystems——一旦我在迁移对象时着手将其重新合并到我的项目中……),正如我所提到的,当您具有双向导航时,这只是一个品味问题。但是当您使用单向导航时(有些人只放置集合,有些人只放置引用),那么您必须从具有导航属性的实体开始-Has
方法需要属性访问器,with
具有无参数重载。
HasMany(c => c.AppUsers).WithRequired(u => u.Company).Map(m => m.MapKey("CompanyID"));
HasMany(c => c.AppUsers).WithRequired(u=>u.Company).Map(u=>u.MapKey("CompanyId"));
HasRequired(u => u.Company);
SELECT
[Extent1].[AppUserId] AS [AppUserId],
[Extent1].[FirstName] AS [FirstName],
[Extent1].[LastName] AS [LastName],
[Extent1].[Email] AS [Email],
[Extent1].[FlowStatus] AS [FlowStatus],
[Extent1].[CompanyId] AS [CompanyId]
FROM [dbo].[AppUser] AS [Extent1]
WHERE ([Extent1].[AppUserId] > 0) AND (N'Joe' = [Extent1].[LastName])