我正在使用 Entity Framework 使用实体拆分将两个表映射在一起,如概述 here和 here .
我发现如果我执行 .ToList()
在 IQueryable<SplitEntity>
上那么结果来自内部联接。但是,如果我采用相同的 IQueryable 并执行 .Count()
它将返回完全连接返回的记录数。
这是一个失败的单元测试:
[TestMethod]
public void GetCustomerListTest()
{
// arrange
List<Customer> results;
int count;
// act
using (var context = new DataContext())
{
results = context.Customers.ToList();
count = context.Customers.Count();
}
// assert
Assert.IsNotNull(results); // succeeds
Assert.IsTrue(results.Count > 0); // succeeds. Has correct records from inner join
Assert.AreEqual(count, results.Count); // This line fails. Has incorrect count from full join.
}
这让我觉得非常糟糕。我如何获得
.Count()
从内部联接返回结果的方法,如 .ToList()
?更新 - SQL
我对完整与内部联接的看法是错误的。
.ToList() 结果:
SELECT
[Extent1].[CustomerNumber] AS [CustomerNumber],
-- ...etc...
[Extent2].[CustomerName] AS [CustomerName],
-- ... etc...
FROM [dbo].[CustomerTable1] AS [Extent1]
INNER JOIN [dbo].[CustomerTable2] AS [Extent2] ON [Extent1].[CustomerNumber] = [Extent2].[CustomerNumber]
.Count() 结果:
SELECT
[GroupBy1].[A1] AS [C1]
FROM ( SELECT
COUNT(1) AS [A1]
FROM [dbo].[customerTable2] AS [Extent1]
) AS [GroupBy1]
更新 - DataContext 和实体代码
数据上下文:
public class DataContext : DbContext
{
public DataContext() { Database.SetInitializer<DataContext>(null); }
public DbSet<Customer> Customers { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Configurations.Add(new CustomerMapping());
}
}
}
客户映射 (FluentAPI):
public class CustomerMapping : EntityTypeConfiguration<Customer>
{
public CustomerMapping()
{
this.Map( m => {
m.Properties( x => new { x.CustomerNumber, /*...etc...*/});
m.ToTable("CustomerTable1");
})
.Map( m => {
m.Properties( x => new { x.CustomerName, /*...etc...*/});
m.ToTable("CustomerTable2");
});
}
}
客户实体:
public class Customer
{
[Key]
public string CustomerNumber { get; set; }
public string CustomerName { get; set; }
}
最佳答案
如果数据库和所有记录都在CustomerTable1
和 CustomerTable2
已由 Entity Framework 和 SaveChanges
创建在您的应用程序代码中调用这种差异不能发生,您可以直接前进和 report this as a bug .
如果您要映射到现有数据库或其他应用程序将记录写入表中,并且您实际上希望不是 CustomerTable1
中的每条记录在CustomerTable2
有对应的记录反之亦然,那么实体拆分是数据库架构的错误映射。
显然,差异意味着您可以拥有 Customer
s 带有 CustomerNumber
(等),但没有 CustomerName
(等) - 或者反过来。对此建模的更好方法是一对一关系,其中一侧是必需的,另一侧是可选的。为此,您将需要一个额外的实体和一个导航属性,例如:
[Table("CustomerTable1")]
public class Customer
{
[Key]
public string CustomerNumber { get; set; }
// + other properties belonging to CustomerTable1
public AdditionalCustomerData AdditionalCustomerData { get; set; }
}
[Table("CustomerTable2")]
public class AdditionalCustomerData
{
[Key]
public string CustomerNumber { get; set; }
public string CustomerName { get; set; }
// + other properties belonging to CustomerTable2
}
使用此 Fluent API 映射:
public class CustomerMapping : EntityTypeConfiguration<Customer>
{
public CustomerMapping()
{
this.HasOptional(c => c.AdditionalCustomerData)
.WithRequired()
.WillCascadeOnDelete(true);
}
}
关于entity-framework - 为什么 Entity Framework 5 在同一实体上执行 .ToList() 与 .Count() 时查询不同的表?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18004090/