ErikEJ / EntityFramework6PowerTools

This is the codebase for Entity Framework 6 Power Tools Community Edition, and modern EF 6 providers for SQL Server and SQL Server Compact
Other
183 stars 26 forks source link

Microsoft.Data.SqlClient provider issues and TODOs #82

Closed ErikEJ closed 3 years ago

ErikEJ commented 3 years ago

IF YOU WANT TO REPORT ISSUES, PLEASE CREATE A NEW ONE

Investigate app.config/web.config transformations (are they needed?)

Consider need for https://github.com/NuGet/Home/issues/5986#issuecomment-732401471

Related: https://github.com/dotnet/ef6/issues/823 https://github.com/dotnet/SqlClient/issues/725

Usage docs here: https://github.com/ErikEJ/EntityFramework6PowerTools#preview-of-ef6-sql-server-provider-based-on-microsoftdatasqlclient

robertmclaws commented 3 years ago

Hey @ErikEJ, seems like the EF Designer has a hard time functioning with Microsoft.Data.SqlClient as the Provider.

app.config in my Data project looks like this:

<?xml version="1.0" encoding="utf-8"?>
<configuration>

  <configSections>
    <section name="entityFramework" type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
  </configSections>

  <connectionStrings>
    <add name="SomeContext" connectionString="metadata=res://*/EntityModel.csdl|res://*/EntityModel.ssdl|res://*/EntityModel.msl;provider=System.Data.SqlClient;provider connection string=&quot;&quot;" providerName="System.Data.EntityClient" />
  </connectionStrings>

  <entityFramework>
    <providers>
      <provider invariantName="Microsoft.Data.SqlClient" type="System.Data.Entity.SqlServer.MicrosoftSqlProviderServices, ErikEJ.EntityFramework.SqlServer" />
    </providers>
  </entityFramework>

  <system.data>
    <clear />
    <DbProviderFactories>
      <add name="SqlClient Data Provider" invariant="Microsoft.Data.SqlClient" type="System.Data.Entity.SqlServer.MicrosoftSqlProviderServices, ErikEJ.EntityFramework.SqlServer"  />
    </DbProviderFactories>
  </system.data>

</configuration>

I'm sure I'm missing something here... any ideas (besides changing it back while I'm editing EDMX files)? Thanks!

ErikEJ commented 3 years ago

@robertmclaws Your connection string seems to still refer to System.Data.SqlClient.

If you have an EDMX, you also need to update the Provider Name in the EDMX file, as per the readme.

robertmclaws commented 3 years ago

Good catch on the connection string. Still getting "Error 175: The ADO.NET provider with invariant name 'Microsoft.Data.SqlClient' is either not registered in the machine or application config file, or could not be loaded. See the inner exception for details." when I try to open the adjusted EDMX file in the designer.

ErikEJ commented 3 years ago

Have you tried to register the provider by hand in machine.config? The VS process needs to know about it, based on the invariant name in the EDMX.

ErikEJ commented 3 years ago

Happy to have a look if you can share a repro .NET Framework project with an EDMX file.

robertmclaws commented 3 years ago

Not sure if I can provide a repro, but we'll see.

Doesn't a machine.config situation mean that the provider would need to be GAC'd, like this: https://github.com/ErikEJ/SqlCeToolbox/wiki/EF6-workflow-with-SQLite-DDEX-provider

ErikEJ commented 3 years ago

Yes, which is most likely not something you want to do.

Again, happy to have a play with a simple repro.

ErikEJ commented 3 years ago

I had a play, I think it is not possible - your system.data section is wrong, though:

https://docs.microsoft.com/en-us/sql/connect/ado-net/obtain-sqlclientfactory?view=sql-server-ver15#register-sqlclientfactory

Final attempt would be to try machine.config, info on how to get the correct values are here: https://github.com/dotnet/SqlClient/issues/836#issuecomment-741698106

(But then you also need to register a copy of the Microsoft.Data.SqlClient.dll in GAC)

robertmclaws commented 3 years ago

GACing + machine.config did not help. Put it in both the 32 and 64 bit machine.config versions, restarted the machine, no dice.

When you open the EDMX file in the text editor with Provider="Microsoft.Data.SqlClient" set, you get a different error: Error 4: The given assembly name or codebase was invalid. (Exception from HRESULT: 0x80131047).

ErikEJ commented 3 years ago

@robertmclaws Thanks, I think we can conclude that this library is a runtime solution (not a design time one) that enables you to move forward, including away from using EDMX files 😄

chuckthompsonprofisee commented 2 years ago

I have a .net 4.7 app that uses EF 6.4.4 and I added your latest version of this assembly. I updated the context and added the required attribute.
but it seems like its still using the system.data.sqlclient as I get this error when trying to connect. The connection string uses a managed identity so it has Authentication=ActiveDirectoryManagedIdentity in the connection string which I know will not work when using the system.data.sqlclient, but it does when using the microsoft.data.sqlclient

Error calling Services.BusinessLogic.SystemCluster.Save ServiceUserName=LocalSystemMessage = Invalid value for key 'authentication'. Source = System.Data StackTrace = at System.Data.Common.DbConnectionStringBuilderUtil.ConvertToAuthenticationType(String keyword, Object value) at System.Data.SqlClient.SqlConnectionString.ConvertValueToAuthenticationType() at System.Data.SqlClient.SqlConnectionFactory.CreateConnectionOptions(String connectionString, DbConnectionOptions previous) at System.Data.SqlClient.SqlConnectionString..ctor(String connectionString) at System.Data.ProviderBase.DbConnectionFactory.GetConnectionPoolGroup(DbConnectionPoolKey key, DbConnectionPoolGroupOptions poolOptions, DbConnectionOptions& userConnectionOptions) at System.Data.SqlClient.SqlConnection.ConnectionString_Set(DbConnectionPoolKey key) at System.Data.SqlClient.SqlConnection.set_ConnectionString(String value) at System.Data.Entity.Infrastructure.Interception.InternalDispatcher1.Dispatch[TTarget,TInterceptionContext](TTarget target, Action2 operation, TInterceptionContext interceptionContext, Action3 executing, Action3 executed) at System.Data.Entity.Infrastructure.SqlConnectionFactory.CreateConnection(String nameOrConnectionString) at System.Data.Entity.Internal.LazyInternalConnection.Initialize() at System.Data.Entity.Internal.LazyInternalConnection.get_ProviderName() at System.Data.Entity.Internal.DefaultModelCacheKeyFactory.Create(DbContext context) 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.InternalSet1.Initialize() at System.Data.Entity.Internal.Linq.InternalSet1.get_InternalContext() at System.Data.Entity.Infrastructure.Interception.DbConnectionDispatcher.SetConnectionString(DbConnection connection, DbConnectionPropertyInterceptionContext1 interceptionContext) at System.Data.Entity.Infrastructure.DbQuery1.System.Linq.IQueryable.get_Provider() at System.Linq.Queryable.FirstOrDefault[TSource](IQueryable1 source) at Profisee.MasterDataMaestro.Services.DataAccess.Repositories.SystemClusterRepository.handleNotificationServer(DbSet1 dbSet, ICollection1 dataContracts, MaestroMessageRequest request, MaestroContext ctx) at Profisee.MasterDataMaestro.Services.DataAccess.Repositories.SystemClusterRepository.preSaveAction(DbSet1 dbSet, ICollection1 dataContracts, MaestroMessageRequest request, MaestroContext ctx) at Profisee.MasterDataMaestro.Services.DataAccess.Repositories.RepositoryBase2.save(ICollection`1 dataContracts, MaestroMessageRequest request, SaveMode saveMode, MaestroContext ctx) TargetSite = System.Data.SqlClient.SqlAuthenticationMethod ConvertToAuthenticationType(System.String, System.Object)

ErikEJ commented 2 years ago

Follow the read me, make sure to reference only my package from all involved projects.

In order to help further I need to see your code.

@chuckthompsonprofisee

eolamisan commented 2 years ago

How to configure "SetDefaultConnectionFactory" with MicrosoftSqlConnectionFactory?

This is what I am trying now:

            SetDefaultConnectionFactory(new MicrosoftSqlConnectionFactory());
            SetProviderFactory(MicrosoftDataSqlClient, SqlClientFactory.Instance);
            SetProviderServices(MicrosoftDataSqlClient, MicrosoftSqlProviderServices.Instance);

            if (ExecutionStrategy != null)
            {
                SetExecutionStrategy(MicrosoftDataSqlClient, ExecutionStrategy);
            }
eolamisan commented 2 years ago

Also, is LocalDb supported? Getting this error message: "Oops! Only SQL Server is currently supported for BatchSaveChanges. More provider is coming soon."

eolamisan commented 2 years ago

Also, is LocalDb supported? Getting this error message: "Oops! Only SQL Server is currently supported for BatchSaveChanges. More provider is coming soon."

Looks like this message is actually coming from a third-party: https://entityframework-extensions.net/batch-savechanges

How to work around that?

ErikEJ commented 2 years ago

@eolamisan

How to configure "SetDefaultConnectionFactory" with MicrosoftSqlConnectionFactory?

Why do you need it - you can just use

DbConfiguration.SetConfiguration(new MicrosoftSqlDbConfiguration()); 

How to work around that?

Ask the author for an update, looks like they have a hardcoded check for System.Data.SqlClient

I am going to lock this issue now. Happy to help you further in new issue(s).

ErikEJ commented 2 years ago

@eolamisan >> This is what I am trying now:

And that does not work?

ErikEJ commented 2 years ago

@eolamisan I have created this issue: https://github.com/zzzprojects/EntityFramework-Extensions/issues/467

ErikEJ commented 2 years ago

Anyone watching this: version 6.5.0-rc1 has been released.

Use M.D.S. 4.0.1 and removes some unused classes from the library, including all spatial and MicrosoftSqlFunctions

ErikEJ commented 6 months ago

UPDATE: my port of this to an official provider has been published https://www.nuget.org/packages/Microsoft.EntityFramework.SqlServer/6.5.0-preview2-24180-01