This is a migrated thread and some comments may be shown as answers.

[Solved] problem in web application.

3 Answers 170 Views
General Discussions
This is a migrated thread and some comments may be shown as answers.
This question is locked. New answers and comments are not allowed.
alex
Top achievements
Rank 1
alex asked on 19 Dec 2010, 08:45 AM
how to develop modules in web application with same connection string id?( Version 2010 Q3)
In previous versions there was no problem.
When using a connection string I get an error.

Type is enhanced and registered, but not available from the database class meta data. This can be caused by a wrong connection id or configuration.
Parameter name: src
Actual value was

3 Answers, 1 is accepted

Sort by
0
Accepted
Alexander
Telerik team
answered on 22 Dec 2010, 10:39 AM
Hello alex,

I assume that you are having multiple domain models (perhaps one for each module) that are using the same database and connection string. Unfortunately at the moment this is not possible out of the box. The problem is that once a connection to the database is obtained, OpenAccess creates internally a Database object which associates the opened database with some metadata. In order to use multiple models with the same database you will have to merge the metadata from all models prior to opening the database and pass the merged content when a connection has to be established for the first time. Some sample code that does the metadata merging is shown in this thread.

However, I think it would be easier for you just to use connection strings with different names. This would save you some time for writing code and it will be easier to switch back to a single connection string when OpenAccess supports this scenario, without modifying the code.

Please note that if you need to change the name of the connection string your rlinq file refers to, you will have to open the rlinq using an xml editor and locate the AppConfigConnectionPropertyName tag, it should be under rlinq : Runtime : ModelSettings. This holds the name of the connection string that is retrieved from the application configuration file.
Hope that helps.

Best wishes,
Alexander
the Telerik team
Accelerate your learning with industry's first Telerik OpenAccess ORM SDK. Download today.
0
alex
Top achievements
Rank 1
answered on 22 Dec 2010, 04:13 PM
Tanks.
Yes. I have multiple domain models in multiple projects. How to merge MetaData in any project?
0
Alexander
Telerik team
answered on 28 Dec 2010, 01:19 PM
Hello alex,

The metadata merging has to be done in your main application after all modules have been loaded and before any module has started working with the database. There are two possible cases based on the architecture of your application. I am not sure which of them fits your scenario, so I will give some details for both of them.

If the main application references the modules directly, you can use the exact same code from the thread I mentioned in my previous post.

However, if the main application is not aware of the modules but the modules reference the application, the approach is a bit different. In the application you will have to provide a collection of MetadataContainer objects which can be accessed and populated by each module. This way when a module loads, it will add its metadata to the global list of metadata containers of the application. In this case it is appropriate to use an ObservableCollection object in order to know when new metadata has been added. Below is all the code you may need to achieve this:
public static class OpenAccessHelper
{
    private static ObservableCollection<MetadataContainer> globalContainer;
    public static ObservableCollection<MetadataContainer> GlobalContainer
    {
        get
        {
            if (globalContainer == null)
            {
                globalContainer = new ObservableCollection<MetadataContainer>();
                globalContainer.CollectionChanged += new System.Collections.Specialized.NotifyCollectionChangedEventHandler(globalContainer_CollectionChanged);
            }
            return globalContainer;
        }
    }
 
    static void globalContainer_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
    {
        //dispose the already loaded database object
        Database cachedDatabase = Database.Get("ConnectionString");
        cachedDatabase.Dispose();
 
        //establish a new database connection with the latest metadata
        Database.Get("ConnectionString", new BackendConfiguration() { Backend = "mssql" }, GetMergedMetadata());
    }
    public static void RegisterMetaContainer(MetadataContainer container)
    {
        GlobalContainer.Add(container);
    }
 
    public static MetadataContainer GetMergedMetadata()
    {
        MetadataContainer metadata = new MetadataContainer();
 
        foreach(MetadataContainer container in GlobalContainer)
        {
            MergeMetaItems(metadata.PersistentTypes, container.PersistentTypes);
            MergeMetaItems(metadata.Tables, container.Tables);
            MergeMetaItems(metadata.Views, container.Views);
            MergeMetaItems(metadata.StoredProcedures, container.StoredProcedures);
            MergeMetaItems(metadata.Constraints, container.Constraints);
            MergeMetaItems(metadata.Indexes, container.Indexes);
        }
 
        return metadata;
    }
 
    static void MergeMetaItems(IList destinationCollection, IEnumerable source)
    {
        foreach(MetaItem item in source)
        {
            if(!ContainsMetaItem(destinationCollection, item))
            {
                destinationCollection.Add(item);
            }
        }
    }
 
    static bool ContainsMetaItem(IList collection, MetaItem metaItem)
    {
        foreach(MetaItem item in collection)
        {
            if(item.Name.Equals(metaItem.Name))
            {
                return true;
            }
        }
        return false;
    }
}

Please note that this code would create a new Database instance for each loaded module. You can avoid that if your application is able to determine when all modules have been loaded. In such a case the ObservableCollection<T> object can be substituted with a normal List<T>. I hope that helps.

Best wishes,
Alexander
the Telerik team
Accelerate your learning with industry's first Telerik OpenAccess ORM SDK. Download today.
Tags
General Discussions
Asked by
alex
Top achievements
Rank 1
Answers by
Alexander
Telerik team
alex
Top achievements
Rank 1
Share this question
or