This project has moved and is read-only. For the latest updates, please go here.

"No table mappings provided" Exception in multi-thread context

Feb 16, 2015 at 6:55 AM
I'm using EntityFramework.BulkInsert in a multi-thread fashion and it works fine while I have one thread or two. But as soon as my thread counts get to 3 or 4 I get "No table mappings provided" Exception.
Mar 23, 2015 at 8:25 PM
Edited Apr 2, 2015 at 9:36 PM
We have encountered this error as well when running multiple threads. A colleague was browsing the code and saw something interesting. It looks like the MappedDataReader makes calls to the extension method Context.Db(type) which is defined in that new EntityFramework.MappingAPI. When he looked at the source for that (at http://efmappingapi.codeplex.com/SourceControl/latest#trunk/src/EntityFramework.MappingAPI/EfMap.cs) he saw this:
/// <summary>
        /// 
        /// </summary>
        /// <param name="context"></param>
        /// <returns></returns>
        public static DbMapping Get(DbContext context)
        {
            var cackeKey = context.GetType().FullName;
#if EF6
            var iDbModelCacheKeyProvider = context as IDbModelCacheKeyProvider;
            if (iDbModelCacheKeyProvider != null)
            {
                cackeKey = iDbModelCacheKeyProvider.CacheKey;
            }
#endif

            if (Mappings.ContainsKey(cackeKey))
            {
                return Mappings[cackeKey];
            }

            var mapping = new DbMapping(context);
            //var mapping = Map(context);

            Mappings[cackeKey] = mapping;
            return mapping;
        }
Could be nothing, but that looks like more caching in a static variable without locks. Possible?
Apr 2, 2015 at 9:15 AM
hi, I've encountered the same issue here with single thread environment
Is there any work around?
Any help will be appreciated, thanks
Apr 2, 2015 at 4:58 PM
Edited Apr 2, 2015 at 6:43 PM
bagamoon wrote:
hi, I've encountered the same issue here with single thread environment
Is there any work around?
Any help will be appreciated, thanks
We put locking in two places and it seems to have resolved the issue. In the BulkInsert library, in the property Providers:
private static readonly object ProviderInitializerLockObject = new object();

private static Dictionary<string, Func<IEfBulkInsertProvider>> Providers
{
    get
    {
        lock (ProviderInitializerLockObject)
       {
            if (_providers == null)
            {
                _providers = new Dictionary<string, Func<IEfBulkInsertProvider>>();

                // bundled providers
                Register<EfSqlBulkInsertProviderWithMappedDataReader>("System.Data.SqlClient.SqlConnection");
                //Register<EfSqlCeBulkiInsertProvider>("System.Data.SqlServerCe.4.0");
            }
        }

        return _providers;
    }
}
And in the MappingAPI solution, in EfMap.cs's Get method:
private static readonly object MappingInitializerLockObject = new object();

public static DbMapping Get(DbContext context)
{
    var cackeKey = context.GetType().FullName;
    DbMapping mapping;
    var iDbModelCacheKeyProvider = context as IDbModelCacheKeyProvider;
    if (iDbModelCacheKeyProvider != null)
    {
        cackeKey = iDbModelCacheKeyProvider.CacheKey;
    }

    lock (MappingInitializerLockObject)
    {

        if (Mappings.ContainsKey(cackeKey))
        {
            mapping = Mappings[cackeKey];
        }
        else
        {
            mapping = new DbMapping(context);
            //var mapping = Map(context);

            Mappings[cackeKey] = mapping;
        }
    }
    return mapping;
}