How to Resolve 'Cannot Modify Dictionary Because ThreadSafeDataLayer Uses It'
- 3 minutes to read
#What Does the Error Message Mean?
The ThreadSafeDataLayer class represents a data access layer for multi-threaded applications. This class ensures immutability of XPDictionary and XPO metadata. You should initialize XPDictionary before you create ThreadSafeDataLayer
.
Important
You shouldn’t create new classes/properties or add attributes after you instantiate a Thread
object. Otherwise, the ‘Cannot Modify Dictionary because Thread
ThreadSafeDataLayer
uses the Fail Fast technique to avoid synchronization issues. When you add a new class to XPDictionary
or modify XPO metadata at runtime, ThreadSafeDataLayer
immediately throws an exception.
#How to Fix the Error?
- Ensure that you add all persistent classes to
XPDictionary
before you initializeThreadSafeDataLayer
. - Ensure that you initialize
ThreadSafeDataLayer
at startup. - Check the class name in the error message. Add this class to XPDictionary at startup.
Dictionary cannot be modified while it's being used by the ThreadSafeDataLayer. ClassInfo modified or created: 'DxSample.Module.BusinessObjects.Contact'
#Review Code that Modifies XPO Metadata
- Turn off the Just My Code option in Visual Studio.
- Review the call stack. Open the Call Stack window and check the output for a non-DevExpress method.
- Go to the method definition (if found) and see if it contains XPDictionary.AddClassInfo, XPDictionary.CreateClass, XPClassInfo.CreateMember, or other method calls. These methods can modify
XPDictinary
. You need to create XPO metadata before you initializeThreadSafeDataLayer
or you can choose not to useThreadSafeDataLayer
(see an example below).
The following example demonstrates how to use a connection pool and SimpleDataLayer to work with XPO objects in a background thread.
public static IDataStore DataStore {
get { return fDataStore; }
}
// In the application entry point
string connectionString = "my connection string";
connectionString = XpoDefault.GetConnectionPoolString(connectionString);
fDataStore = XpoDefault.GetConnectionProvider(connectionString, AutoCreateOption.None);
XpoDefault.DataLayer = new SimpleDataLayer(DataStore);
// In a background thread
XPDictionary dictionary = new ReflectionDictionary();
IDataLayer dataLayer = new SimpleDataLayer(dictionary, Program.DataStore);
Session session = new Session(dataLayer);
#Generic Persistent Classes Don’t Map to Specific Tables
When you use a generic type with a specific argument, XPO creates new persistent metadata. Do not create metadata dynamically. Decorate generic classes with the NonPersistentAttribute attribute, declare non-generic descendants, and map them to tables.
#‘Cannot modify Dictionary because ThreadSafeDataLayer uses it’ in XAF
In XAF applications, this error occurs when new records are added to the XPObjectType table after the data access layer has been initialized. Use the DBUpdater tool to update your database and fill the XPObjectType table in advance.