EF CTP5 Code First DatabaseInitializer和EFTracingConnection [英] EF CTP5 Code First DatabaseInitializer and EFTracingConnection

查看:54
本文介绍了EF CTP5 Code First DatabaseInitializer和EFTracingConnection的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用Jarek Kowalski的EFTracingConnection包装器( http://code.msdn.microsoft.com/EFProviderWrappers ) 使用EF CTP5 Code First跟踪生成的t-sql。只要我设置


我就得到
工作

          ;     DbDatabase  .SetInitializer<  MyContainer >( null ); 

正如Jarek在这里提到的那样
http://jkowalski.com/2010/04/23/logging-sql-statements-in-entity-frameworkcode-first /
 一个限制是包装器不能与使用SqlClient提供程序创建数据库一起工作(Jarek在他的示例中使用了ObjectContext。我使用DbContext)。如果
我使用数据库初始化程序  ;我得到一个System.ArgumentException"给定的提供者清单不是'System.Data.SqlClient.SqlProviderManifest'类型。"具有以下堆栈跟踪


  在System.Data.SqlClient.SqlProviderServices.GetSqlVersion(StoreItemCollection storeItemCollection)

  在System.Data.SqlClient.SqlProviderServices.DbCreateDatabase(DbConnection连接,Nullable`1 commandTimeout,StoreItemCollection storeItemCollection)

  在System.Data.Common.DbProviderServices.CreateDatabase(DbConnection连接,Nullable`1 commandTimeout,StoreItemCollection storeItemCollection)

  在EFProviderWrapperToolkit.DbProviderServicesBase.DbCreateDatabase(DbConnection连接,Nullable`1 commandTimeout,StoreItemCollection storeItemCollection)中的C:\Projects \ EF4ProviderWrappers \ EFProviderWrapperToolkit \DbProviderServicesBase.cs:line
143


因此,如果我想使用数据库初始化程序,我使用一个未包装的连接。在我的案例中,在Glabal.asax.cs

            ;   DbDatabase  .SetInitializer<  MyContainer >( new    DatabaseInitializer ()); 

              使用 ( MyContainer   context  =  ; new   MyContainer ())
      ;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP; {
&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;   context.Database.Initialize( false );
            ;&NBSP;}&NBSP;&NBSP;&NBSP;&NBSP;&NBSP ;    

 但是,如果我想在数据库之后使用EFTracingConnection(在我的情况下在RIA Services DomainService中)初始化程序已运行,我得到一个System.NotSupportedException"使用相同的DbModel来创建针对不同类型的上下文
的数据库服务器不受支持。而是为每种正在使用的服务器创建一个单独的DbModel。具有以下堆栈跟踪


  在System.Data.Entity.Internal.CodeFirstCachedMetadataWorkspace.GetMetadataWorkspace(DbConnection连接)

  在System.Data.Entity.Infrastructure.DbModel.CreateObjectContext [TContext](DbConnection existingConnection)

  在System.Data.Entity.Internal.LazyInternalContext.InitializeContext()

  在System.Data.Entity.Internal.InternalContext.Initialize()

   at System.Data.Entity.Internal.InternalContext.GetEntitySetAndBaseTypeForType(Type entityType)

  在System.Data.Entity.Internal.Linq.InternalSet`1.Initialize()

  在System.Data.Entity.Internal.Linq.InternalSet`1.GetEnumerator()

   at System.Data.Entity.Infrastructure.DbQuery`1.System.Collections.IEnumerable.GetEnumerator()

  在System.ServiceModel.DomainServices.Server.DomainService.Enumerate [T](IEnumerable enumerable,Int32 estimatedResultCount)

  在System.ServiceModel.DomainServices.Server.DomainService.Query(QueryDescription queryDescription,IEnumerable`1& validationErrors,Int32& totalCount)


在使用ObjectContext的Jarek示例中,这不是问题使用Code First,但是当我使用DbContext和数据库初始化程序时,这是一个问题。因为我首先使用了一个解包的连接,然后是一个包装的连接,所以EF
Code First CTP5认为我使用的是针对不同数据库服务器的相同模型,但当然它是相同的数据库服务器。如上所述,只要我不使用数据库初始化程序,因此它只能使用包装连接。我
已尝试设置

               DbDatabase  .SetInitializer<  MyContainer >(在Global.asax.cs中的代码之后,再次); 

,但这没有任何区别。有没有其他人设法让EFTracingConnection与Code First和数据库初始化程序一起工作?  


亲切的问候


Remco

解决方案

Remco,


 


我不认为您将能够使用数据库初始化程序与Jarek的包装提供程序,因为它不支持提供程序API的必要部分。 
此外,EF还标识了提供商类型使用的数据库类型以及来自该提供商的信息—这是设计使然并且不太可能改变。 
编译模型的Code First的内部缓存绑定到正在使用的数据库的提供者/类型,因为模型本身在编译时绑定到提供者。 &NBSP;
但是,您可以执行自己的缓存—此线程有一些关于如何执行此操作的信息:
http ://social.msdn.microsoft.com/Forums/en-US/adonetefx/thread/fb3eaba4-d12c-4eb5-b9c1-4acacd2fff3c/
然后,您可以创建绑定到常规SQL客户端提供程序的模型,并将其用于数据库创建等,并创建一个单独的模型(来自同一个模型构建器),该模型绑定到Jarek的提供程序,用于其余的app。 
这显然比使用内部缓存更复杂,但除非你能让Jarek更新他的代码以支持Code First,否则很可能是获得工作的最佳选择。


 


谢谢,


Arthur


I am trying to use Jarek Kowalski's EFTracingConnection wrapper (http://code.msdn.microsoft.com/EFProviderWrappers) to get tracing of generated t-sql using EF CTP5 Code First. I got it working as long as I set

            DbDatabase.SetInitializer<MyContainer>(null);

As Jarek mentioned here http://jkowalski.com/2010/04/23/logging-sql-statements-in-entity-frameworkcode-first/ a limitation is that the wrapper does not work with database creation with the SqlClient provider (Jarek uses a ObjectContext in his example. I use a DbContext). If I use a database initializer I get a System.ArgumentException "The provider manifest given is not of type 'System.Data.SqlClient.SqlProviderManifest'." with the following stack trace

   at System.Data.SqlClient.SqlProviderServices.GetSqlVersion(StoreItemCollection storeItemCollection)
   at System.Data.SqlClient.SqlProviderServices.DbCreateDatabase(DbConnection connection, Nullable`1 commandTimeout, StoreItemCollection storeItemCollection)
   at System.Data.Common.DbProviderServices.CreateDatabase(DbConnection connection, Nullable`1 commandTimeout, StoreItemCollection storeItemCollection)
   at EFProviderWrapperToolkit.DbProviderServicesBase.DbCreateDatabase(DbConnection connection, Nullable`1 commandTimeout, StoreItemCollection storeItemCollection) in C:\Projects\EF4ProviderWrappers\EFProviderWrapperToolkit\DbProviderServicesBase.cs:line 143

So, if I want to use a database initializer, I use an unwrapped connection. In my case in Glabal.asax.cs

            DbDatabase.SetInitializer<MyContainer>(new DatabaseInitializer());

            using (MyContainer context = new MyContainer())
            {
                context.Database.Initialize(false);
            }         

 However, if I then want to use the EFTracingConnection (in my case in a RIA Services DomainService) after the database initializer has run, I get a System.NotSupportedException "Using the same DbModel to create contexts against different types of database servers is not supported. Instead, create a separate DbModel for each type of server being used." with the following stack trace

   at System.Data.Entity.Internal.CodeFirstCachedMetadataWorkspace.GetMetadataWorkspace(DbConnection connection)
   at System.Data.Entity.Infrastructure.DbModel.CreateObjectContext[TContext](DbConnection existingConnection)
   at System.Data.Entity.Internal.LazyInternalContext.InitializeContext()
   at System.Data.Entity.Internal.InternalContext.Initialize()
   at System.Data.Entity.Internal.InternalContext.GetEntitySetAndBaseTypeForType(Type entityType)
   at System.Data.Entity.Internal.Linq.InternalSet`1.Initialize()
   at System.Data.Entity.Internal.Linq.InternalSet`1.GetEnumerator()
   at System.Data.Entity.Infrastructure.DbQuery`1.System.Collections.IEnumerable.GetEnumerator()
   at System.ServiceModel.DomainServices.Server.DomainService.Enumerate[T](IEnumerable enumerable, Int32 estimatedResultCount)
   at System.ServiceModel.DomainServices.Server.DomainService.Query(QueryDescription queryDescription, IEnumerable`1& validationErrors, Int32& totalCount)

This was not a problem in Jarek's example where he uses an ObjectContext with Code First, but it is a problem when I use a DbContext and a database initializer .Just because I use an unwrapped connection first and then a wrapped connection, EF Code First CTP5 thinks I am using the same model against different database servers, but of course it is the same database server. As mentioned it works fine as long as I dont use a database initializer and therefore only use the wrapped connection. I have tried setting

            DbDatabase.SetInitializer<MyContainer>(null);

again after the code in the Global.asax.cs, but that made no difference. Has anybody else managed to get the EFTracingConnection working with Code First and a database initializer?  

kind regards

Remco

解决方案

Remco,

 

I don’t think that you will be able to use database initializers with Jarek’s wrapping provider since it doesn’t support the necessary parts of the provider API.  Also, EF identifies the type of database it is being used against by the provider type and information from that provider—this is by design and is unlikely to change.  The internal caching that Code First for the compiled model is bound to the provider/type of database being used because the model itself, when compiled, is bound to the provider.  However, you can perform your own caching instead—this thread has some info on how to do that: http://social.msdn.microsoft.com/Forums/en-US/adonetefx/thread/fb3eaba4-d12c-4eb5-b9c1-4acacd2fff3c/. You could then create a model bound to the regular SQL client provider and use this for database creation, etc, and create a separate model (from the same ModelBuilder) that is bound to Jarek’s provider for the rest of your app.  This is obviously more complicated than using the internal caching, but is likely to be your best bet for getting something working unless you can get Jarek to update his code to support Code First.

 

Thanks,

Arthur


这篇关于EF CTP5 Code First DatabaseInitializer和EFTracingConnection的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆