Description:
MySql Connector/.Net EntityFramework's provider throws NullReferenceException when trying to INSERT a new record with no values (INSERT INTO table VALUES() ), e.g. when a table only contains a PK Autoincrement column.
In InsertGenerator, GenerateSql(), the values collection is not initialized if there are no values, but is called anyway in GenerateReturningSql().
How to repeat:
Here's a simple test case :
MySql Schema (not needed if you use 6.6 alpha):
CREATE DATABASE `test`;
CREATE TABLE `test`.`VeryUsefulObjects` (
`ID` int(11) NOT NULL AUTO_INCREMENT,
PRIMARY KEY (`ID`)
);
app.config :
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<connectionStrings>
<add name="SuicidalContext" connectionString="server=mysqlserver;database=test;user=user;password=password" providerName="MySql.Data.MySqlClient" />
</connectionStrings>
</configuration>
Little C# + Entity Framework console app :
using System;
using System.Data.Entity;
namespace SuicidalTendency
{
class CrashingProgram
{
public static void Main(string[] args)
{
using (SuicidalContext sc = new SuicidalContext() ) {
sc.VeryUsefulObjects.Add( new VeryUsefulObject() );
sc.SaveChanges(); // throws NullReferenceException
}
}
}
}
public class VeryUsefulObject
{
public int ID { get; set; }
}
public class SuicidalContext : DbContext
{
public DbSet<VeryUsefulObject> VeryUsefulObjects { get; set; }
}
Suggested fix:
In MySql.Data.Entity.InsertGenerator, replace :
foreach (DbSetClause setClause in commandTree.SetClauses)
{
DbExpression value = setClause.Value;
SqlFragment valueFragment = value.Accept(this);
statement.Values.Add(valueFragment);
if (values == null)
values = new Dictionary<EdmMember, SqlFragment>();
if (value.ExpressionKind != DbExpressionKind.Null)
{
EdmMember property = ((DbPropertyExpression)setClause.Property).Property;
values.Add(property, valueFragment);
}
}
by
if (values == null)
values = new Dictionary<EdmMember, SqlFragment>();
foreach (DbSetClause setClause in commandTree.SetClauses)
{
DbExpression value = setClause.Value;
SqlFragment valueFragment = value.Accept(this);
statement.Values.Add(valueFragment);
if (value.ExpressionKind != DbExpressionKind.Null)
{
EdmMember property = ((DbPropertyExpression)setClause.Property).Property;
values.Add(property, valueFragment);
}
}