Fixing the EF Tracing and Caching Provider Wrapper Issue
If you have been using the Tracing and Caching Provider Wrappers for the ADO.NET Entity Framework 4.0, you might of come across this error message when creating POCO objects, adding them to a Data Context and commiting them to the database using the Caching Wrapper:
[NotImplementedException: The method or operation is not implemented.] EFCachingProvider.EFCachingDataReaderCacheWriter.GetName(Int32 ordinal) in EFCachingProvider\EFCachingDataReaderCacheWriter.cs:109 System.Data.Mapping.Update.Internal.DynamicUpdateCommand.Execute(UpdateTranslator translator, EntityConnection connection, Dictionary`2 identifierValues, List`1 generatedValues) +8118458 System.Data.Mapping.Update.Internal.UpdateTranslator.Update(IEntityStateManager stateManager, IEntityAdapter adapter) +267
Line 107: public override string GetName(int ordinal)
Line 108: {
Line 109: throw new NotImplementedException();
Line 110: }
Line 111:
Basically, the author’s of the code have created a wrapper for the DBDataReader class and have not implement the override methods. This can be fixed by calling the Wrapper DataReader object methods. This is what I have modified in the EFCachignDataReaderCacheWriter.cs file:
using System;
using System.Data;
using System.Data.Common;
using EFCachingProvider.Caching;
namespace EFCachingProvider
{
///
/// Implementation of the which reads the results of another data reader
/// and stores a copy in the cache.
///
internal class EFCachingDataReaderCacheWriter : EFCachingDataReaderBase
{
private DbQueryResults queryResults = new DbQueryResults();
private DbDataReader wrappedReader;
private int maxRows;
private Action addToCache;
///
/// Initializes a new instance of the EFCachingDataReaderCacheWriter class.
///
///
<span> </span>The wrapped reader. ///
<span> </span>The maximum number of rows which can be cached. ///
The delegate used to add the result to the cache when the reader finishes. public EFCachingDataReaderCacheWriter(DbDataReader wrappedReader, int maxRows, Action addToCache)
{
this.wrappedReader = wrappedReader;
this.addToCache = addToCache;
this.maxRows = maxRows;
}
///
/// Gets a value that indicates whether this contains one or more rows.
///
///
/// true if the contains one or more rows; otherwise false.
///
public override bool HasRows
{
get { return this.wrappedReader.HasRows; }
}
///
/// Gets the number of rows changed, inserted, or deleted by execution of the SQL statement.
///
///
///
/// The number of rows changed, inserted, or deleted. -1 for SELECT statements; 0 if no rows were affected or the statement failed.
///
public override int RecordsAffected
{
//get { throw new NotImplementedException(); }
get { return this.wrappedReader.RecordsAffected; }
}
///
/// Gets a value indicating whether the is closed.
///
///
/// true if the is closed; otherwise false.
///
public override bool IsClosed
{
//get { throw new NotImplementedException(); }
get { return this.wrappedReader.IsClosed; }
}
///
/// Gets a value indicating the depth of nesting for the current row.
///
///
///
/// The depth of nesting for the current row.
///
public override int Depth
{
//get { throw new NotImplementedException(); }
get { return this.wrappedReader.Depth; }
}
///
/// Gets name of the data type of the specified column.
///
///
The zero-based column ordinal. ///
/// A string representing the name of the data type.
///
public override string GetDataTypeName(int ordinal)
{
//throw new NotImplementedException();
return this.wrappedReader.GetDataTypeName(ordinal);
}
///
/// Gets the data type of the specified column.
///
///
The zero-based column ordinal. /// The data type of the specified column.
public override Type GetFieldType(int ordinal)
{
return this.wrappedReader.GetFieldType(ordinal);
}
///
/// Gets the name of the column, given the zero-based column ordinal.
///
///
The zero-based column ordinal. /// The name of the specified column.
public override string GetName(int ordinal)
{
return this.wrappedReader.GetName(ordinal);
}
///
/// Gets the column ordinal given the name of the column.
///
///
The name of the column. /// The zero-based column ordinal.
///
/// The name specified is not a valid column name.
///
public override int GetOrdinal(string name)
{
return this.wrappedReader.GetOrdinal(name);
}
///
/// Returns a that describes the column metadata of the .
///
///
/// A that describes the column metadata.
///
public override DataTable GetSchemaTable()
{
return this.wrappedReader.GetSchemaTable();
}
///
/// Advances the reader to the next result when reading the results of a batch of statements.
///
///
/// true if there are more result sets; otherwise false.
///
public override bool NextResult()
{
if (this.wrappedReader.NextResult())
{
this.queryResults = null;
return true;
}
else
{
return false;
}
}
///
/// Closes the object.
///
public override void Close()
{
this.wrappedReader.Close();
if (this.queryResults != null)
{
this.addToCache(this.queryResults);
}
}
///
/// Advances the reader to the next record in a result set.
///
///
/// true if there are more rows; otherwise false.
///
public override bool Read()
{
if (this.wrappedReader.Read())
{
object[] values = new object[this.wrappedReader.FieldCount];
this.wrappedReader.GetValues(values);
SetValues(values);
if (this.queryResults != null)
{
this.queryResults.Rows.Add(values);
if (this.queryResults.Rows.Count > this.maxRows)
{
this.queryResults = null;
}
}
return true;
}
else
{
return false;
}
}
}
}
using System.Data;
using System.Data.Common;
using EFCachingProvider.Caching;
namespace EFCachingProvider
{
///
/// Implementation of the which reads the results of another data reader
/// and stores a copy in the cache.
///
internal class EFCachingDataReaderCacheWriter : EFCachingDataReaderBase
{
private DbQueryResults queryResults = new DbQueryResults();
private DbDataReader wrappedReader;
private int maxRows;
private Action addToCache;
///
/// Initializes a new instance of the EFCachingDataReaderCacheWriter class.
///
///
<span> </span>The wrapped reader. ///
<span> </span>The maximum number of rows which can be cached. ///
The delegate used to add the result to the cache when the reader finishes. public EFCachingDataReaderCacheWriter(DbDataReader wrappedReader, int maxRows, Action addToCache)
{
this.wrappedReader = wrappedReader;
this.addToCache = addToCache;
this.maxRows = maxRows;
}
///
/// Gets a value that indicates whether this contains one or more rows.
///
///
/// true if the contains one or more rows; otherwise false.
///
public override bool HasRows
{
get { return this.wrappedReader.HasRows; }
}
///
/// Gets the number of rows changed, inserted, or deleted by execution of the SQL statement.
///
///
///
/// The number of rows changed, inserted, or deleted. -1 for SELECT statements; 0 if no rows were affected or the statement failed.
///
public override int RecordsAffected
{
//get { throw new NotImplementedException(); }
get { return this.wrappedReader.RecordsAffected; }
}
///
/// Gets a value indicating whether the is closed.
///
///
/// true if the is closed; otherwise false.
///
public override bool IsClosed
{
//get { throw new NotImplementedException(); }
get { return this.wrappedReader.IsClosed; }
}
///
/// Gets a value indicating the depth of nesting for the current row.
///
///
///
/// The depth of nesting for the current row.
///
public override int Depth
{
//get { throw new NotImplementedException(); }
get { return this.wrappedReader.Depth; }
}
///
/// Gets name of the data type of the specified column.
///
///
The zero-based column ordinal. ///
/// A string representing the name of the data type.
///
public override string GetDataTypeName(int ordinal)
{
//throw new NotImplementedException();
return this.wrappedReader.GetDataTypeName(ordinal);
}
///
/// Gets the data type of the specified column.
///
///
The zero-based column ordinal. /// The data type of the specified column.
public override Type GetFieldType(int ordinal)
{
return this.wrappedReader.GetFieldType(ordinal);
}
///
/// Gets the name of the column, given the zero-based column ordinal.
///
///
The zero-based column ordinal. /// The name of the specified column.
public override string GetName(int ordinal)
{
return this.wrappedReader.GetName(ordinal);
}
///
/// Gets the column ordinal given the name of the column.
///
///
The name of the column. /// The zero-based column ordinal.
///
/// The name specified is not a valid column name.
///
public override int GetOrdinal(string name)
{
return this.wrappedReader.GetOrdinal(name);
}
///
/// Returns a that describes the column metadata of the .
///
///
/// A that describes the column metadata.
///
public override DataTable GetSchemaTable()
{
return this.wrappedReader.GetSchemaTable();
}
///
/// Advances the reader to the next result when reading the results of a batch of statements.
///
///
/// true if there are more result sets; otherwise false.
///
public override bool NextResult()
{
if (this.wrappedReader.NextResult())
{
this.queryResults = null;
return true;
}
else
{
return false;
}
}
///
/// Closes the object.
///
public override void Close()
{
this.wrappedReader.Close();
if (this.queryResults != null)
{
this.addToCache(this.queryResults);
}
}
///
/// Advances the reader to the next record in a result set.
///
///
/// true if there are more rows; otherwise false.
///
public override bool Read()
{
if (this.wrappedReader.Read())
{
object[] values = new object[this.wrappedReader.FieldCount];
this.wrappedReader.GetValues(values);
SetValues(values);
if (this.queryResults != null)
{
this.queryResults.Rows.Add(values);
if (this.queryResults.Rows.Count > this.maxRows)
{
this.queryResults = null;
}
}
return true;
}
else
{
return false;
}
}
}
}


