MVC and Entity Framework : Unable to retrieve the metadata for the model

Let’s say you are developing an MVC application and you want to add a generated controller with the associated views.

You do this:

  1. Setting the controller’s name
  2. Choosing the template: mvc controller with read/write actions and views, using Entity Framework
  3. Choosing the model class
  4. Choosing the data context
  5. Clicking “Add”

image001

It’s possible that you get this error:

image002

The solution is quite simple:

Just go in the web.config file and comment the connection string

image004

Then try again

image005

It works!

Don’t forget to uncomment your connection string and you are done.

Incoming search terms:

  • unable to retrieve metadata for model class
  • MVCandEntityFramework:Unabletoretrievethemetadataforthemodel
  • unable to retrieve metadata for
  • unable to retrieve metadata for model
  • unable to retrieve metadata for mvc
  • unable to retrieve metadata
  • entity framework unable to retrieve metadata
  • asp net mvc unable to retrieve metadata
  • mvc unable to retrieve metadata
  • yhs-fullyhosted_003

Quick tip: list all poco’s properties and their values

Let’s say you have a poco and you want to list all its properties whith their values for debug purpose (or other purposes : logs, …)

You can write something like this :


string porperties = "property1 : " + this.property1;
porperties+="property : " + this.property2;
// ..
porperties+="propertyn : " + this.propertyn;

but it’s long and painful, plus you can forget some properties

The reflection can help us here :


string porperties = "";
 foreach (System.Reflection.PropertyInfo f in this.GetType().GetProperties())
 {
porperties += f.Name + " : " + f.GetValue(this, null) + Environment.NewLine;
 }

And if you want to be a bit clever, you create a base object and redefine the ‘ToString() method like this:


public class POCOBase
{
public override string ToString()
{
string ret = "";
foreach (System.Reflection.PropertyInfo f in this.GetType().GetProperties())
{
ret += f.Name + " : " + f.GetValue(this, null) + Environment.NewLine;
  }
  return ret;
 }
}

Then just inherit from POCOBase and call the ToString() method

The output should be something like this :

AccountID : 10
ExternalREF : 090xfe
FIRSTNAME : USER 1
LASTNAME : TEST
PHONE : 00044440000
RegisterDate : 30/09/2009 16:20:02
Remark :

I think it’s quick, easy and useful

Bring a bit of the Subsonic power to Entity Framework by adding automatic audit and logical delete fields

Here is the code to do the same thing than in my previous article “Bring a bit of the Subsonic power to Linq to sql by adding automatic audit and logical delete fields”


namespace YouNamespace.DAL
{
 using System;
 using System.Collections;
 using System.Collections.Generic;
 using System.Collections.ObjectModel;
 using System.Data;
 using System.Data.Common;
 using System.Data.Objects;
 using System.Linq;

 public partial class YOURCONTEXTEntities
 {
 /// <summary>
 /// System fields for automatic audit and logical delete
 /// </summary>
 private struct SystemFields
 {
 public const string CreatedOn = "CREATEDON";
 public const string ModifiedOn = "MODIFIEDON";
 public const string CreatedBy = "CREATEDBY";
 public const string ModifiedBy = "MODIFIEDBY";
 public const string IsDeleted = "ISDELETED";
 }

 /// <summary>
 /// Overriding the SaveChanges method to automaticaly set system fields if any.
 /// </summary>
 /// <param name="options"></param>
 /// <returns></returns>
 public override int SaveChanges(System.Data.Objects.SaveOptions options)
 {
 IEnumerable<ObjectStateEntry> newEntries = this.ObjectStateManager.GetObjectStateEntries(EntityState.Added);

 foreach (ObjectStateEntry entry in newEntries)
 {
 ReadOnlyCollection<FieldMetadata> fieldsMetaData = entry.CurrentValues
 .DataRecordInfo.FieldMetadata;

 FieldMetadata createdOnField = fieldsMetaData
 .Where(f => string.Equals(f.FieldType.Name, SystemFields.CreatedOn, StringComparison.OrdinalIgnoreCase)).FirstOrDefault();

 if (createdOnField.FieldType != null)
 {
 entry.CurrentValues.SetValue(createdOnField.Ordinal, DateTime.Now);
 }

 FieldMetadata createdByField = fieldsMetaData
 .Where(f => string.Equals(f.FieldType.Name, SystemFields.CreatedBy, StringComparison.OrdinalIgnoreCase)).FirstOrDefault();

 if (createdByField.FieldType != null)
 {
 entry.CurrentValues.SetValue(createdByField.Ordinal, "Sam");
 }

 FieldMetadata deletedField = fieldsMetaData
 .Where(f => string.Equals(f.FieldType.Name, SystemFields.IsDeleted, StringComparison.OrdinalIgnoreCase)).FirstOrDefault();

 if (deletedField.FieldType != null)
 {
 entry.CurrentValues.SetValue(deletedField.Ordinal, false);
 }
 }

 IEnumerable<ObjectStateEntry> modifiedEntries = this.ObjectStateManager.GetObjectStateEntries(EntityState.Modified);
 foreach (ObjectStateEntry entry in modifiedEntries)
 {
 ReadOnlyCollection<FieldMetadata> fieldsMetaData = entry.CurrentValues
 .DataRecordInfo.FieldMetadata;

 FieldMetadata createdOnField = fieldsMetaData
 .Where(f => string.Equals(f.FieldType.Name, SystemFields.ModifiedOn, StringComparison.OrdinalIgnoreCase)).FirstOrDefault();

 if (createdOnField.FieldType != null)
 {
 entry.CurrentValues.SetValue(createdOnField.Ordinal, DateTime.Now);
 }

 FieldMetadata createdByField = fieldsMetaData
 .Where(f => string.Equals(f.FieldType.Name, SystemFields.ModifiedBy, StringComparison.OrdinalIgnoreCase)).FirstOrDefault();

 if (createdByField.FieldType != null)
 {
 entry.CurrentValues.SetValue(createdByField.Ordinal, "Sam");
 }
 }

 IEnumerable<ObjectStateEntry> deletedEntries = this.ObjectStateManager.GetObjectStateEntries(EntityState.Deleted);
 foreach (ObjectStateEntry entry in deletedEntries)
 {
 // change from deleted to modified (!important)
 this.ObjectStateManager.ChangeObjectState(entry.Entity, EntityState.Modified);

 ReadOnlyCollection<FieldMetadata> fieldsMetaData = entry.CurrentValues
 .DataRecordInfo.FieldMetadata;

 FieldMetadata deletedField = fieldsMetaData
 .Where(f => string.Equals(f.FieldType.Name, SystemFields.IsDeleted, StringComparison.OrdinalIgnoreCase)).FirstOrDefault();

 if (deletedField.FieldType != null)
 {
 entry.CurrentValues.SetValue(deletedField.Ordinal, true);
 }
else
 {
 // change back from modified to deleted (!important)
 this.ObjectStateManager.ChangeObjectState(entry.Entity, EntityState.Deleted);
 }
 }

 return base.SaveChanges(options);
 }
 }
}

Incoming search terms:

  • entry currentvalues
  • subsonic audit
  • subsonic createdon
  • subsonic entity framework
  • subsonic Leave a Reply comment -captcha

Debugging ADO.NET Datatables

Do you ever had the famous error message :

“Failed to enable constraints. One or more rows  contain values violating non-null, unique, or foreign-key  constraints.”

when using ADO.NET Datasets ?

Tthis is an incredibly useful message isn’t it ?

So what can you do to spare you some headaches ? Retrieve a more useful message sure !

You have to know that a Datatable object have a “HasError” property, this property allows you to know if the datatable has one ore more rows in error.

When HasError is true, you can retrieve the rows havin an error with the DataTable’s “GetErrors()” method wich return an array with all datarow having an error.

The “in errror” rows can inform you about errors with the “RowError” property.

Here is a simple helper class which can be used to debug a single DataTable or an entire DataSet:

using System;
using System.Data;

public class DataSetErrorRevealer
{

   /// <summary>
   /// Get errors on rows of a DataTable
   /// </summary>
   /// <param name="errorDataTable">The DataTable to be checked</param>
   public static void RevealTableErrors(DataTable errorDataTable)
   {
      if (errorDataTable == null)
      {
         Console.WriteLine("The provided DataTable object is null");
         return;
      }

      if (errorDataTable.HasErrors)
      {
         DataRow[] rowsInError = errorDataTable.GetErrors();
         if (rowsInError.Length <= 0)
         {
            Console.WriteLine("There is no problem with table {0}", errorDataTable.TableName);
         }
         else
         {
            foreach (DataRow errorRow in rowsInError)
            {
               Console.WriteLine(errorRow.RowError);
            }
         }
      }
   }

   /// <summary>
   /// Get errors on row for all tables of a DataSet
   /// </summary>
   /// <param name="errorDataSet">The Dataset to be checked</param>
   public static void RevealDataSetErrors(DataSet errorDataSet)
   {
         if (errorDataSet == null)
         {
            Console.WriteLine("The provided DataSet is null");
            return;
         }

         foreach (DataTable errorTable in errorDataSet.Tables)
         {
            RevealTableErrors(errorTable);
         }
      }
   }

Use it this way :


   TestDataSet dataset = new TestDataSet();
   try
   {
      using (SqlConnection sqlCon = new SqlConnection("MyConnectionString"))
      {
         SqlCommand sqlComm = sqlCon.CreateCommand();
         sqlComm.CommandType = CommandType.StoredProcedure;
         sqlComm.CommandText = "Select Stored procedure";
         SqlDataAdapter sqlDa = new SqlDataAdapter(sqlComm);
         sqlDa.Fill(dataset);
      }
   }
   catch (Exception ex)
   {
   // Will provide the error message :
   // "Failed to enable constraints. One or more rows
   // contain values violating non-null, unique,
   // or foreign-key  constraints."
   Console.WriteLine("Error : {0}", ex);

   // will provide a more helpful message
   DataSetErrorRevealer.RevealDataSetErrors(dataset);
   }

If you prefer, you can use an extension method :


using System.Data;
using System;

public static class DataSetExtensions
{
   public static void RevealErrors(this DataSet errorDataSet)
   {
      if (errorDataSet == null)
      {
         Console.WriteLine("The provided DataSet is null");
         return;
      }

      foreach (DataTable errorTable in errorDataSet.Tables)
      {
         errorTable.RevealErrors();
      }
   }

   public static void RevealErrors(this DataTable errorDataTable)
   {
      if (errorDataTable == null)
      {
         Console.WriteLine("The provided DataTable object is null");
         return;
      }

      if (errorDataTable.HasErrors)
      {
         DataRow[] rowsInError = errorDataTable.GetErrors();
         if (rowsInError.Length <= 0)
         {
            Console.WriteLine("There is no problem with table {0}", errorDataTable.TableName);
         }
         else
         {
            foreach (DataRow errorRow in rowsInError)
            {
               Console.WriteLine(errorRow.RowError);
            }
         }
      }
   }
}

use :


catch (Exception ex)
{
   // will provide an helpful message
   dataset.RevealErrors();
}

Hope this helps !

using System;
using System.Data;public class DataSetErrorRevealer
{

/// <summary>
/// Get errors on rows of a DataTable
/// </summary>
/// <param name=”errorDataTable”>The DataTable to be checked</param>
public static void RevealTableErrors(DataTable errorDataTable)
{
if (errorDataTable == null)
{
Console.WriteLine(“The provided DataTable object is null”);
return;
}

if (errorDataTable.HasErrors)
{
DataRow[] rowsInError = errorDataTable.GetErrors();
if (rowsInError.Length <= 0)
{
Console.WriteLine(“There is no problem with table {0}”, errorDataTable.TableName);
}
else
{
foreach (DataRow errorRow in rowsInError)
{
Console.WriteLine(errorRow.RowError);
}
}
}
}

/// <summary>
/// Get errors on row for all tables of a DataSet
/// </summary>
/// <param name=”errorDataSet”>The Dataset to be checked</param>
public static void RevealDataSetErrors(DataSet errorDataSet)
{
if (errorDataSet == null)
{
Console.WriteLine(“The provided DataSet is null”);
return;
}

foreach (DataTable errorTable in errorDataSet.Tables)
{
RevealTableErrors(errorTable);
}
}
}

Incoming search terms:

  • datatable geterrors
  • datatable haserrors
  • debugging You may use these HTML tags and attributes -captcha