Bug #66066 Using EF, crash when generating insert with no values.
Submitted: 28 Jul 2012 13:08 Modified: 28 Sep 2012 18:54
Reporter: Damien BRUN Email Updates:
Status: Closed Impact on me:
None 
Category:Connector / NET Severity:S3 (Non-critical)
Version:6.5.4, 6.6 alpha OS:Windows
Assigned to: Fernando Gonzalez.Sanchez CPU Architecture:Any
Tags: entityframework

[28 Jul 2012 13:08] Damien BRUN
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);
        }
      }
[28 Sep 2012 18:54] John Russell
Added to changelog for 6.4.6, 6.5.5, 6.6.3: 

The MySQL Connector/Net EntityFramework provider would throw
NullReferenceException when trying to insert a new record with an
empty VALUES clause. Such an INSERT should work when the only
required (NOT NULL) column in the table is a primary key
auto-increment column.