Hi,
Lately I've been testing EF6 and I must say I'm very impressed with all the improvements! Can't wait for the RTM version to be shipped.
While testing with EF6-Beta1 I think I found a bug. It's easy to reproduce.
My database has 2 tables crm.Relation and history.Relation table, the history.Relation table contains the same set of fields as the crm.Relation table (for auditing changes) as well as a VersionId field (int) and an UpdatedOn field (datetime).
Entities are defined as:
When I capture the queries and run them on the database, each record of the last customer correctly shows another version, no duplicate versionnumbers for it.
That's why I think this is a bug that should be fixed. I'm using .NET 4.5, VS2012 Update 3, EF 6.0.0.0 and SQL Server 2012. Can anyone confirm that this is indeed a bug?
UPDATE:
When I change the content of the second foreach to:
Perhaps this helps to find the rootcause.
Best regards,
Jeroen
Lately I've been testing EF6 and I must say I'm very impressed with all the improvements! Can't wait for the RTM version to be shipped.
While testing with EF6-Beta1 I think I found a bug. It's easy to reproduce.
My database has 2 tables crm.Relation and history.Relation table, the history.Relation table contains the same set of fields as the crm.Relation table (for auditing changes) as well as a VersionId field (int) and an UpdatedOn field (datetime).
Entities are defined as:
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations.Schema;
using System.Data.Entity;
using System.Data.Entity.ModelConfiguration;
namespace POC_TablePerType
{
public interface IMyDbContext : IDisposable
{
IDbSet<crm_Relatie> crm_Relatie { get; set; } // Relatie
IDbSet<crm_RelatieHistorie> crm_RelatieHistorie { get; set; } // RelatieHistorie
int SaveChanges();
}
public partial class MyDbContext : DbContext, IMyDbContext
{
public IDbSet<crm_Relatie> crm_Relatie { get; set; }
public IDbSet<crm_RelatieHistorie> crm_RelatieHistorie { get; set; }
static MyDbContext()
{
Database.SetInitializer<MyDbContext>(null);
}
public MyDbContext() : base("Name=MyDbContext") { }
public MyDbContext(string connectionString) : base(connectionString) { }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Configurations.Add(new crm_RelatieConfiguration());
modelBuilder.Configurations.Add(new crm_RelatieHistorieConfiguration());
}
}
public partial class crm_Relatie
{
public int RelatieId { get; set; }
public string Zoeksleutel { get; set; }
public string Relatienaam { get; set; }
public crm_Relatie() { }
}
internal partial class crm_RelatieConfiguration : EntityTypeConfiguration<crm_Relatie>
{
public crm_RelatieConfiguration()
{
ToTable("crm.Relatie");
HasKey(x => x.RelatieId);
Property(x => x.RelatieId).HasColumnName("RelatieID").IsRequired().HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
Property(x => x.Zoeksleutel).HasColumnName("Zoeksleutel").IsRequired().HasMaxLength(5);
Property(x => x.Relatienaam).HasColumnName("Relatienaam").IsRequired().HasMaxLength(40);
}
}
public class crm_RelatieHistorie : crm_Relatie
{
public int VersieId { get; set; }
public DateTime GewijzigdOp { get; set; }
}
internal partial class crm_RelatieHistorieConfiguration : EntityTypeConfiguration<crm_RelatieHistorie>
{
public crm_RelatieHistorieConfiguration()
{
ToTable("history.Relatie");
HasKey(x => new { x.RelatieId, x.VersieId });
}
}
}
Tables are created as:CREATE TABLE [crm].[Relatie](
[RelatieID] [int] IDENTITY(1,1) NOT NULL,
[Zoeksleutel] [nchar](5) NOT NULL,
[Relatienaam] [nvarchar](40) NOT NULL,
[fkContactpersoonID] [int] NULL,
[fkVerantwoordelijkeRAID] [int] NULL,
CONSTRAINT [PK_Relatie] PRIMARY KEY CLUSTERED
(
[RelatieID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
CREATE TABLE [history].[Relatie](
[GewijzigdOp] [datetime] NOT NULL,
[VersieID] [int] NOT NULL,
[RelatieID] [int] NOT NULL,
[Zoeksleutel] [nchar](5) NOT NULL,
[Relatienaam] [nvarchar](40) NOT NULL,
CONSTRAINT [PK_Relatie] PRIMARY KEY CLUSTERED
(
[RelatieID] ASC,
[VersieID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [HISTORY]
) ON [HISTORY]
The problem is easy to see when I run this code: using (var db = new MyDbContext())
{
Console.WriteLine("Selecting just the fields I need:");
/* Runs this query:
SELECT
[Extent1].[RelatieID] AS [RelatieID],
[Extent1].[VersieId] AS [VersieId],
[Extent2].[Relatienaam] AS [Relatienaam]
FROM [history].[Relatie] AS [Extent1]
INNER JOIN [crm].[Relatie] AS [Extent2] ON [Extent1].[RelatieID] = [Extent2].[RelatieID]
*/
var relaties = from r in db.crm_RelatieHistorie
select new {r.RelatieId, r.VersieId, r.Relatienaam};
foreach (var rel in relaties)
Console.WriteLine(String.Format("Name: {0}\tVersion: {1}",rel.Relatienaam, rel.VersieId));
Console.WriteLine("\nSelecting the object itself:");
/* Runs this query:
SELECT
'0X0X' AS [C1],
[Extent1].[RelatieID] AS [RelatieID],
[Extent2].[Zoeksleutel] AS [Zoeksleutel],
[Extent2].[Relatienaam] AS [Relatienaam],
[Extent1].[VersieId] AS [VersieId],
[Extent1].[GewijzigdOp] AS [GewijzigdOp]
FROM [history].[Relatie] AS [Extent1]
INNER JOIN [crm].[Relatie] AS [Extent2] ON [Extent1].[RelatieID] = [Extent2].[RelatieID]
*/
var relaties2 = from r in db.crm_RelatieHistorie select r;
foreach (var rel in relaties2)
Console.WriteLine(String.Format("Name: {0}\tVersion: {1}", rel.Relatienaam, rel.VersieId));
}
Console.ReadLine();
}
Althought both queries (see comments in code) are almost equal, they show different results:Selecting just the fields I need:
Name: A company Version: 1
Name: B company Version: 1
Name: C company Version: 1
Name: D company Version: 1
Name: Customer-With-4-Versions Version: 1
Name: Customer-With-4-Versions Version: 2
Name: Customer-With-4-Versions Version: 3
Name: Customer-With-4-Versions Version: 4
Selecting the object itself:
Name: A company Version: 1
Name: B company Version: 1
Name: C company Version: 1
Name: D company Version: 1
Name: Customer-With-4-Versions Version: 1
Name: Customer-With-4-Versions Version: 1
Name: Customer-With-4-Versions Version: 1
Name: Customer-With-4-Versions Version: 1
The history table contains 4 different versions of the last customer so the former output is correct whereas the latter incorrectly shows version 1 for each instance.When I capture the queries and run them on the database, each record of the last customer correctly shows another version, no duplicate versionnumbers for it.
That's why I think this is a bug that should be fixed. I'm using .NET 4.5, VS2012 Update 3, EF 6.0.0.0 and SQL Server 2012. Can anyone confirm that this is indeed a bug?
UPDATE:
When I change the content of the second foreach to:
Console.WriteLine(String.Format("Name: {0}\tVersion: {1}", rel.Relatienaam, rel.VersieId));
if (rel.VersieId == 1) rel.VersieId = 10;
the output becomes:Selecting just the fields I need:
Name: A company Version: 1
Name: B company Version: 1
Name: C company Version: 1
Name: D company Version: 1
Name: Customer-With-4-Versions Version: 1
Name: Customer-With-4-Versions Version: 2
Name: Customer-With-4-Versions Version: 3
Name: Customer-With-4-Versions Version: 4
Selecting the object itself:
Name: A company Version: 1
Name: B company Version: 1
Name: C company Version: 1
Name: D company Version: 1
Name: Customer-With-4-Versions Version: 1
Name: Customer-With-4-Versions Version: 10
Name: Customer-With-4-Versions Version: 10
Name: Customer-With-4-Versions Version: 10
Looks like some some invalid reference to an entity instance.Perhaps this helps to find the rootcause.
Best regards,
Jeroen