qua*_*els 6 linq-to-entities entity-framework entity-framework-5
我正在使用Entity Framework使用Entity Splitting将两个表映射到一起,如此处和此处所述.
我发现如果我执行一个.ToList()
on 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.
}
Run Code Online (Sandbox Code Playgroud)
这让我觉得非常糟糕.我怎样才能让.Count()
方法从内部连接返回结果.ToList()
?
我对完全与内部连接错了.
.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]
Run Code Online (Sandbox Code Playgroud)
.Count()导致:
SELECT
[GroupBy1].[A1] AS [C1]
FROM ( SELECT
COUNT(1) AS [A1]
FROM [dbo].[customerTable2] AS [Extent1]
) AS [GroupBy1]
Run Code Online (Sandbox Code Playgroud)
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());
}
}
}
Run Code Online (Sandbox Code Playgroud)
客户映射(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");
});
}
}
Run Code Online (Sandbox Code Playgroud)
客户实体:
public class Customer
{
[Key]
public string CustomerNumber { get; set; }
public string CustomerName { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
如果数据库以及Entity Framework中创建的所有记录CustomerTable1
和应用程序代码中的调用都不会发生这种差异,您可以直接将其报告为错误.CustomerTable2
SaveChanges
如果要映射到现有数据库,或者其他应用程序将记录写入表中,并且实际上您希望不是每个记录CustomerTable1
都有相应的记录,CustomerTable2
反之亦然,那么Entity Splitting是您的数据库模式的错误映射.
很明显的区别意味着你可以拥有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
}
Run Code Online (Sandbox Code Playgroud)
使用此Fluent API映射:
public class CustomerMapping : EntityTypeConfiguration<Customer>
{
public CustomerMapping()
{
this.HasOptional(c => c.AdditionalCustomerData)
.WithRequired()
.WillCascadeOnDelete(true);
}
}
Run Code Online (Sandbox Code Playgroud)