Is there a way to generate the mapping and model classes with DB-first, without relying on the Visual Designer or even better without Visual Studio? Is there a command line tool or an API for this purpose?
Our problem is that we have a really large number of tables - 1000+, yes I know :) - and takes an eternity for VS to generate all that stuff. When it doesn't crash.
Thanks!
8 Answers, 1 is accepted
For very large databases, Telerik OpenAccess ORM offers an alternative to Visual Designer - Fluent Mapping API. There you can define the classes and mapping in a code-only manner and use them with OpenAccess without ever touching Visual Designer.
To make things easier for you, the Create New Domain Model wizard implements "Fluent" as an option for code generation. It generates most of the necessary code automatically and at the same time you can benefit from the capabilities this API offers. Generally, it is intended to be used as onetime code generation only and its purpose is to help you with the initial effort in defining the data access layer.
To build your model using Fluent code generation, follow the next steps:
1) Add Telerik OpenAccess Library to your solution
2) Follow steps from 4 to 9 described here
3) In the Advanced Options dialogue of the wizard:
- select Fluent for mapping type
- choose Project folder - the folder where the classes will be generated
- check the Generate multiple files checkbox (optional - it depends on your personal preference for the number of the files and their length. If you check it you will have a file for every class and if you uncheck it, you will have one really long file)
4) Extract the OpenAccessContext as describe here.
5) Delete the .rlinq file
Note: That will not reduce the initial time for generating the model but it will make it easier for you to work with it afterwards as you can make changes in the code directly.
Additionally, in the midst of February we are releasing Telerik OpenAccess ORM Q1 2013 where you can find the new Fluent Code Generation wizard that will additionally help you during that process.
If you experience any difficulties implementing this process or you have questions, do not hesitate to get back to us.
Greetings,
Doroteya
the Telerik team
So I've taken your advice and switched to Fluent API mapping.
There is one performance aspect that is worse than with XML mapping: the context instance creation takes longer after the initial creation.
More exactly, here are some execution times:
XML mapping:
First context instantiation: 10.59 sec
First query execution: 04.24 sec
Second context instantiation: 00.0002 sec
Second query execution: 00.01 sec
Fluent mapping:
First context instantiation: 10.56 sec
First query execution: 04.13 sec
Second context instantiation: 02.34 sec <== the problem
Second query execution: 00.01 sec
The 10 sec for the first context creation (cold start-up) are somewhat ok but 2+ seconds for each sub-sequential context instantiation it is a problem. Any idea why this happens and how can this be reduced ?
Thanks.
So in my derived class (e.g. MyProjectFluentMetadataSource) I've overridden this method and cached the model in a class field. This means it will call base.CreateModel() only the first time.
This is in fact making the MetadataContainer instance a singleton for the whole app domain life. Because MyProjectFluentMetadataSource is already a singleton being stored in a static field of the MyContext class.
This results in getting sub 0.0 seconds for every context initialization except the first one.
Do you see any bad side effects with reusing the same instance of this MetadataContainer ?
Thanks
Given your setup I believe your solution is viable and should not provide any problems or risks. The only side effect would be if you are dynamically adding more configuration files during runtime and the cached container will not really allow you that but since this is not the case in your scenario I believe you should be fine.
Kind regards,Petar
the Telerik team
A further improvement of the context start up would be to serialize the MetadataContainer instance.
Unfortunately this cannot be done because Telerik.OpenAccess.Metadata.MetaItemAttributeCollection is not marked as Serializable. There may be other classes in this situation referred by MetadataContainer.
How hard is to make MetadataContainer serializable in a future version or patch ?
Thanks.
The MetadataContainer is marked as Serializable. The attirbutes collection is intentionally not mapped as serializable as it is constructed dynamically based on what properties you have set (it contains only the non default ones).
.
Petar
the Telerik team
Caching the MetadataContainer instance seems like such a common performance scenario, I'm unsure why it's not done by default. This code gives us similar performance improvements.
public partial class ContextModel : OpenAccessContext
{
private static string defaultConnectionStringName = @"ContextConnection";
private static BackendConfiguration backend = GetBackendConfiguration();
private static MetadataSource _metadataSource;
private static MetadataContainer _metadataContainer;
static ContextModel()
{
if (_metadataSource == null)
{
_metadataSource = new ContextModelMetadataSource();
_metadataContainer = _metadataSource.GetModel();
}
}
public ContextModel()
: base(defaultConnectionStringName, backend, _metadataContainer)
{
}
Thank you for your feedback. Your approach is fine and definitely beneficial if you have an application with a static model. If you build your model and it remains static through all the live of the app domain there is no reason to not cache the MetadataContainer.
The MetadataContainer is not cached by default because of the support of more dynamic scenarios. Such caching will be a problem with all cases in which the model is extended through the live of your application - new tables, properties, associations are mapped, etc.
Regards,
Simeon Simeonov
Telerik