Entity Framework 联接是否应该在父级 table 中包含 table?
Should an Entity Framework join contain the table within the parent table?
我定义了以下实体:
public partial class ImportConnection
{
public int id { get; set; }
public int fkCompanyID { get; set; }
public int fkUserTypeID { get; set; }
public int fkDataConnection { get; set; }
public System.DateTime RecordCreated { get; set; }
public Nullable<System.DateTime> RecordUpdated { get; set; }
public string ConnectionName { get; set; }
public bool isEnabled { get; set; }
public bool isPrimary { get; set; }
public bool ManageUsersOnImport { get; set; }
public bool ManageGroupsOnImport { get; set; }
public bool isValidated { get; set; }
public bool isErrored { get; set; }
public int XLoc { get; set; }
public int YLoc { get; set; }
public int FrequencyInMinutes { get; set; }
public Nullable<System.DateTime> ScheduledStartTime { get; set; }
public Nullable<System.DateTime> ActualStart { get; set; }
public Nullable<System.DateTime> QueuedTime { get; set; }
public Nullable<System.DateTime> ActualCompletion { get; set; }
public int LastRunLengthTime { get; set; }
public string ImportQuery { get; set; }
public string IdentityColumn { get; set; }
public string LastRunMessage { get; set; }
public virtual Company Company { get; set; } //<---- here
public virtual UserType UserType { get; set; }
public virtual DataConnector DataConnector { get; set; } //<---- and here
}
我正在使用以下查询从数据库加载 table。我也加入了另外两个 table。如果我在 SQL Server Management Studio 中 运行 这个(必须稍微修改查询)我得到了公司和数据连接器所以我知道数据库中的数据是正确的(键匹配)。
List<ImportConnection> dcList = await (from data in db.ImportConnection
join dc in db.DataConnector on data.fkDataConnection equals dc.id
join co in db.Company on data.fkCompanyID equals co.Id
where data.ScheduledStartTime < DateTime.Now
&& data.isEnabled == true
&& dc.isValidated == true
&& !data.isErrored
select data).ToListAsync();
但是,加载查询后,我从 ImportConnection
获取数据,但 Company
和 DataConnector
均为空。
连接中的 table 不应该显示在顶部实体对象中吗?如果是,是什么原因导致数据未显示?
如果您不使用架构使用的命名约定配置 EF,EF 将采用 FK 的约定默认值。设置导航属性后,您无需在 Linq 表达式中添加联接,只需将它们 .Include()
添加到 eager-load,或者让 EF Lazy 按需加载它们。
如果您启用了迁移,您可能会发现您的 table 已按照 EF 的默认约定添加了诸如“CompanyID”之类的列。
要配置您的 FK:
[ForeignKey("Company")]
public int fkCompanyID { get; set; }
[ForeignKey("UserType")]
public int fkUserTypeID { get; set; }
[ForeignKey("DataConnection")]
public int fkDataConnection { get; set; }
然后查询:
List<ImportConnection> dcList = await db.ImportConnection
.Include(x => x.DataConnector)
.Include(x => x.UserType)
.Include(x => x.Company)
.Where( x => x.ScheduledStartTime < DateTime.Now
&& x.isEnabled
&& x.DataConnector.isValidated
&& !x.isErrored)
.ToListAsync();
要检查的另一件事是,您的关系是否针对 many-to-one 正确设置,而不是一对一。在 EF6 中,如果关系标记为 one-to-one,则 EF 将在两个 table 上使用 PK 作为相关 FK。
即如果您的 EntityTypeConfiguration / modelBuilder 配置引用:
.HasRequired(x => x.Company)
.WithRequired(x => x.ImportConnection)
如果 ImportConnection 有一个公司,而公司有一个 ImportConnection,则 EF 将在 Company 上加入此 CompanyId,并在 ImportConnection 上加入 ImportConnectionId。这可能会导致从关系返回预期或不正确数据的问题。
应该是many-to-one连接:
.HasRequired(x => x.Company)
.WithMany() // Assuming Company does not have a collection of ImportConnections.
// or .WithMany(x => x.ImportConnections) if it does.
这是我明确配置 EF 而不是依赖约定的原因之一。这样,要么 EF 告诉我存在问题,要么按照我可以检查和更正而不是猜测的方式行事,以及它正在解释什么约定。
我定义了以下实体:
public partial class ImportConnection
{
public int id { get; set; }
public int fkCompanyID { get; set; }
public int fkUserTypeID { get; set; }
public int fkDataConnection { get; set; }
public System.DateTime RecordCreated { get; set; }
public Nullable<System.DateTime> RecordUpdated { get; set; }
public string ConnectionName { get; set; }
public bool isEnabled { get; set; }
public bool isPrimary { get; set; }
public bool ManageUsersOnImport { get; set; }
public bool ManageGroupsOnImport { get; set; }
public bool isValidated { get; set; }
public bool isErrored { get; set; }
public int XLoc { get; set; }
public int YLoc { get; set; }
public int FrequencyInMinutes { get; set; }
public Nullable<System.DateTime> ScheduledStartTime { get; set; }
public Nullable<System.DateTime> ActualStart { get; set; }
public Nullable<System.DateTime> QueuedTime { get; set; }
public Nullable<System.DateTime> ActualCompletion { get; set; }
public int LastRunLengthTime { get; set; }
public string ImportQuery { get; set; }
public string IdentityColumn { get; set; }
public string LastRunMessage { get; set; }
public virtual Company Company { get; set; } //<---- here
public virtual UserType UserType { get; set; }
public virtual DataConnector DataConnector { get; set; } //<---- and here
}
我正在使用以下查询从数据库加载 table。我也加入了另外两个 table。如果我在 SQL Server Management Studio 中 运行 这个(必须稍微修改查询)我得到了公司和数据连接器所以我知道数据库中的数据是正确的(键匹配)。
List<ImportConnection> dcList = await (from data in db.ImportConnection
join dc in db.DataConnector on data.fkDataConnection equals dc.id
join co in db.Company on data.fkCompanyID equals co.Id
where data.ScheduledStartTime < DateTime.Now
&& data.isEnabled == true
&& dc.isValidated == true
&& !data.isErrored
select data).ToListAsync();
但是,加载查询后,我从 ImportConnection
获取数据,但 Company
和 DataConnector
均为空。
连接中的 table 不应该显示在顶部实体对象中吗?如果是,是什么原因导致数据未显示?
如果您不使用架构使用的命名约定配置 EF,EF 将采用 FK 的约定默认值。设置导航属性后,您无需在 Linq 表达式中添加联接,只需将它们 .Include()
添加到 eager-load,或者让 EF Lazy 按需加载它们。
如果您启用了迁移,您可能会发现您的 table 已按照 EF 的默认约定添加了诸如“CompanyID”之类的列。
要配置您的 FK:
[ForeignKey("Company")]
public int fkCompanyID { get; set; }
[ForeignKey("UserType")]
public int fkUserTypeID { get; set; }
[ForeignKey("DataConnection")]
public int fkDataConnection { get; set; }
然后查询:
List<ImportConnection> dcList = await db.ImportConnection
.Include(x => x.DataConnector)
.Include(x => x.UserType)
.Include(x => x.Company)
.Where( x => x.ScheduledStartTime < DateTime.Now
&& x.isEnabled
&& x.DataConnector.isValidated
&& !x.isErrored)
.ToListAsync();
要检查的另一件事是,您的关系是否针对 many-to-one 正确设置,而不是一对一。在 EF6 中,如果关系标记为 one-to-one,则 EF 将在两个 table 上使用 PK 作为相关 FK。
即如果您的 EntityTypeConfiguration / modelBuilder 配置引用:
.HasRequired(x => x.Company)
.WithRequired(x => x.ImportConnection)
如果 ImportConnection 有一个公司,而公司有一个 ImportConnection,则 EF 将在 Company 上加入此 CompanyId,并在 ImportConnection 上加入 ImportConnectionId。这可能会导致从关系返回预期或不正确数据的问题。
应该是many-to-one连接:
.HasRequired(x => x.Company)
.WithMany() // Assuming Company does not have a collection of ImportConnections.
// or .WithMany(x => x.ImportConnections) if it does.
这是我明确配置 EF 而不是依赖约定的原因之一。这样,要么 EF 告诉我存在问题,要么按照我可以检查和更正而不是猜测的方式行事,以及它正在解释什么约定。