Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Microsoft.Data.SqlClient provider issues and TODOs #82

Closed
ErikEJ opened this issue Jul 28, 2021 · 70 comments
Closed

Microsoft.Data.SqlClient provider issues and TODOs #82

ErikEJ opened this issue Jul 28, 2021 · 70 comments

Comments

@ErikEJ
Copy link
Owner

ErikEJ commented Jul 28, 2021

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

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

Consider need for NuGet/Home#5986 (comment)

Related: dotnet#823 dotnet/SqlClient#725

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

@ErikEJ ErikEJ changed the title MDS notes Microsoft.Data.SqlClient provider issues and TODOs Jul 29, 2021
@ErikEJ
Copy link
Owner Author

ErikEJ commented Jul 29, 2021

@ajcvickers given the current lack of plans for the EF6 repo, I assume that a PR to add support for Microsoft.Data.SqlClient is out of the question?

Given that, are you OK with the package name (ErikEJ.EntityFramework.SqlServer) ?

@ajcvickers
Copy link

@ErikEJ I don't think it's out of the question. On the other hand, it's not going to happen immediately, so it probably makes sense to have an external package for now. Name seems good to me. /cc @bricelam since he's good at package naming.

@bricelam
Copy link

Couldn't have picked a better name myself. 😉

Regarding the transforms, I think (based on dotnet#953 (comment)) that they're not actually needed. But I honestly can't remember the details.

@jvanderwoude80
Copy link

Hi, thank you very much for this package! It would solve our issues, however I can't make it work yet. My scenario: Migrated from a working .NET framework 4.6.1 app using EF6 to communicate with an AzureDb with Always Encrypted to a .NET Core 3.1 app. Had to use Microsoft.Data.SqlClient.AlwaysEncrypted.AzureKeyVaultProvider and thus Microsoft.Data.SqlClient. This (of course) did not work because M.D.S was not supported in EF6.

Tried using this new package in the following way:

using System.Data.Entity;
using Microsoft.Data.SqlClient;

[DbConfigurationType(typeof(System.Data.Entity.SqlServer.MicrosoftSqlDbConfiguration))]
public partial class MyDb : DbContext
{
    public MyDb(SqlConnection connection) : base(connection, true)
    {
        Database.SetInitializer<MyDb>(null);
        this.Configuration.LazyLoadingEnabled = false;
        this.Configuration.ProxyCreationEnabled = false;
    }
}

Using a constructor with an exising SQL connection (using Microsoft.Data.SqlClient) containing the connection string and token for access to the DB and master pw for always encrypted. However this fails on the first call to the DB (in another connector class): db.Database.ExecuteSqlCommand with the same error as before using the new package:

System.NotSupportedException : Unable to determine the provider name for provider factory of type 'Microsoft.Data.SqlClient.SqlClientFactory'. Make sure that the ADO.NET provider is installed or registered in the application config.

Is this a scenario that should work now? Or did I miss or something / configured incorrectly? Help would be appreciated. Thanks!

@ErikEJ
Copy link
Owner Author

ErikEJ commented Aug 10, 2021

@jvanderwoude80 I am not able to repro, please provide a full repro.

Maybe this needs to run before an data access code (if this fixes your issue, I can add this line to the DbConfiguration class)

DbProviderFactories.RegisterFactory("Microsoft.Data.SqlClient", Microsoft.Data.SqlClient.SqlClientFactory.Instance);

@jvanderwoude80
Copy link

@ErikEJ thanks! Sorry, full repro is kinda difficult because the app is using a private incompany (confidential) nuget framework containing the entity code and models of the specific DB, and (maybe part of the problem) also other DB connectors also using EF6 (but with System.Data.SqlClient) so both ErikEJ.EntityFramework.SqlServer.dll and EntityFramework.SqlServer.dll are in the bin folder.. So I hope this code fragments will do..

Anyway, above line of code (when used in the constructor above) does change the behavior, but gives this error:
System.InvalidOperationException : No Entity Framework provider found for the ADO.NET provider with invariant name 'Microsoft.Data.SqlClient'. Make sure the provider is registered in the 'entityFramework' section of the application config file. See http://go.microsoft.com/fwlink/?LinkId=260882 for more information.
Also tried using an app.config (not sure if possible in .NET core), but same error.

Any ideas? Do you need other code fragments or debug information that will help? Thanks again!

@ErikEJ
Copy link
Owner Author

ErikEJ commented Aug 10, 2021

Are you using .NET Framework libraries from .NET Core? That could cause issues, I believe. The need to be rebuilt for .NET Standard or .NET Core/5.

Happy to take a Teams session to get to the bottom of this, if you think that may help.

@jvanderwoude80
Copy link

I'm not sure, but I guess a teams session would surely help to sort it out.

@ErikEJ
Copy link
Owner Author

ErikEJ commented Aug 10, 2021

You can contact me on ejlskov at hotmail dot com...

@ErikEJ
Copy link
Owner Author

ErikEJ commented Aug 12, 2021

@jvanderwoude80 You had multiple DbContext classes in your solution, and the fix was to add the attribute to them all!

[DbConfigurationType(typeof(System.Data.Entity.SqlServer.MicrosoftSqlDbConfiguration))]

@jvanderwoude80
Copy link

Yes, that fixed it. Thank you very much!

Summarizing: With your package I now have a working .NET Core 3.1 solution with EF6 using the new Microsoft.Data.SqlClient. Also always encrypted (on a Azure SQL DB) using Microsoft.Data.SqlClient.AlwaysEncrypted.AzureKeyVaultProvider is working.

@ErikEJ
Copy link
Owner Author

ErikEJ commented Aug 13, 2021

I have just published a 1.0-rc1 package based on your feedback!

@jvanderwoude80
Copy link

jvanderwoude80 commented Aug 13, 2021 via email

@robertmclaws
Copy link

robertmclaws commented Aug 16, 2021

Hey folks! Having a problem getting this going in our project with the RC1 build. We're still using EDMX files because they are wicked awesome for codegen. To use EDMX files in EF6 on .NET Core, it requires building an EntityConnection manually, so we wrote a constructor overload and a helper to make this happen.

DbContext Code:

using CloudNimble.BurnRate.Core;
using System.Data.Entity;
using System.Data.Entity.Core.EntityClient;
using System.Data.Entity.Infrastructure;

namespace CloudNimble.BurnRate.Data
{

    /// <summary>
    /// 
    /// </summary>
    public partial class BurnRateContext : DbContext
    {
           
        /// <summary>
        ///
        /// </summary>
        public BurnRateContext() : base("name=SomeConnectionString")
        {
        }
        
        /// <summary>
        /// Creates a new <see cref="BurnRateContext"/> instance for a given connection string.
        /// </summary>
        /// <param name="sqlConnectionString">A SqlClient connection string that does not have EntityClient metadata.</param>
        public BurnRateContext(string sqlConnectionString) : base(GetEntityConnection(sqlConnectionString), true)
        {
        }
               
        /// <summary>
        ///
        /// </summary>
        protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {
            throw new UnintentionalCodeFirstException();
        }
        
        /// <summary>
        /// 
        /// </summary>
        /// <param name="sqlConnectionString">A SqlClient connection string that does not have EntityClient metadata.</param>
        /// <returns>an <see cref="EntityConnection" /> object populated with the default values for an BurnRateContext EF6 connection.</returns>
        private static EntityConnection GetEntityConnection(string sqlConnectionString)
        {
            var entityBuilder = new EntityConnectionStringBuilder()
            {
                Provider = "Microsoft.Data.SqlClient",
                ProviderConnectionString = sqlConnectionString,
                Metadata = @"res://*/EntityModel.csdl|res://*/EntityModel.ssdl|res://*/EntityModel.msl",
            };
            return new EntityConnection(entityBuilder.ToString());
        }
        
        #endregion
        
    }
    
}

Now we can pull the connectionstring from .NET Core Configuration, pass it in, and get the job done.

Except that it appears that EntityConnectionStringBuilder is hard-coded to use System.Data.SqlClient.SqlConnection.

CloudNimble.BurnRate.Api2 Error: 0 : Exception: Unable to cast object of type 'Microsoft.Data.SqlClient.SqlConnection' to type 'System.Data.SqlClient.SqlConnection'. 
StackTrace:    at void System.Data.SqlClient.SqlCommand.set_DbConnection(DbConnection value)
   at void System.Data.Common.DbCommand.set_Connection(DbConnection value)
   at void System.Data.Entity.Internal.InterceptableDbCommand.set_DbConnection(DbConnection value)
   at void System.Data.Common.DbCommand.set_Connection(DbConnection value)
   at void System.Data.Entity.Core.Common.Utils.CommandHelper.SetStoreProviderCommandState(EntityCommand entityCommand, EntityTransaction entityTransaction, DbCommand storeProviderCommand)
   at DbCommand System.Data.Entity.Core.EntityClient.Internal.EntityCommandDefinition.PrepareEntityCommandBeforeExecution(EntityCommand entityCommand)
   at async Task<DbDataReader> System.Data.Entity.Core.EntityClient.Internal.EntityCommandDefinition.ExecuteStoreCommandsAsync(EntityCommand entityCommand, CommandBehavior behavior, CancellationToken cancellationToken)
   at T System.Data.Entity.Utilities.TaskExtensions+CultureAwaiter<T>.GetResult()
   at async Task<ObjectResult<TResultType>> System.Data.Entity.Core.Objects.Internal.ObjectQueryExecutionPlan.ExecuteAsync<TResultType>(ObjectContext context, ObjectParameterCollection parameterValues, CancellationToken cancellationToken)
   at T System.Data.Entity.Utilities.TaskExtensions+CultureAwaiter<T>.GetResult()
   at async Task<T> System.Data.Entity.Core.Objects.ObjectContext.ExecuteInTransactionAsync<T>(Func<Task<T>> func, IDbExecutionStrategy executionStrategy, bool startLocalTransaction, bool releaseConnectionOnSuccess, CancellationToken cancellationToken)
   at async Task<TResult> System.Data.Entity.SqlServer.DefaultSqlExecutionStrategy.ExecuteAsyncImplementation<TResult>(Func<Task<TResult>> func)
   at T System.Data.Entity.Utilities.TaskExtensions+CultureAwaiter<T>.GetResult()
   at async Task<ObjectResult<T>> System.Data.Entity.Core.Objects.ObjectQuery<T>.GetResultsAsync(MergeOption? forMergeOption, IDbExecutionStrategy executionStrategy, CancellationToken cancellationToken)
   at T System.Data.Entity.Utilities.TaskExtensions+CultureAwaiter<T>.GetResult()
   at async Task<bool> System.Data.Entity.Internal.LazyAsyncEnumerator<T>.FirstMoveNextAsync(CancellationToken cancellationToken)
   at async Task System.Data.Entity.Infrastructure.IDbAsyncEnumerableExtensions.ForEachAsync<T>(IDbAsyncEnumerator<T> enumerator, Action<T> action, CancellationToken cancellationToken)
   at T System.Data.Entity.Utilities.TaskExtensions+CultureAwaiter<T>.GetResult()
   at async Task<T[]> System.Data.Entity.Infrastructure.IDbAsyncEnumerableExtensions.ToArrayAsync<T>(IDbAsyncEnumerable<T> source, CancellationToken cancellationToken)
   at async Task<QueryResult> Microsoft.Restier.EntityFramework.EFQueryExecutor.ExecuteQueryAsync<TElement>(QueryContext context, IQueryable<TElement> query, CancellationToken cancellationToken)
   at async Task<QueryResult> Microsoft.Restier.AspNetCore.Query.RestierQueryExecutor.ExecuteQueryAsync<TElement>(QueryContext context, IQueryable<TElement> query, CancellationToken cancellationToken)
   at async Task<QueryResult> Microsoft.Restier.Core.Query.DefaultQueryHandler.QueryAsync(QueryContext context, CancellationToken cancellationToken)
   at async Task<QueryResult> Microsoft.Restier.Core.ApiBaseExtensions.QueryAsync(ApiBase api, QueryRequest request, CancellationToken cancellationToken)
   at async Task<IQueryable> Microsoft.Restier.AspNetCore.RestierController.ExecuteQuery(IQueryable queryable, CancellationToken cancellationToken)
   at async Task<IActionResult> Microsoft.Restier.AspNetCore.RestierController.Get(CancellationToken cancellationToken)
   at async ValueTask<IActionResult> Microsoft.AspNetCore.Mvc.Infrastructure.ActionMethodExecutor+TaskOfIActionResultExecutor.Execute(IActionResultTypeMapper mapper, ObjectMethodExecutor executor, object controller, object[] arguments)
   at async Task Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.InvokeActionMethodAsync()+Logged(?)
   at async Task Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.InvokeNextActionFilterAsync()+Awaited(?)
   at void Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Rethrow(ActionExecutedContextSealed context)
   at Task Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Next(ref State next, ref Scope scope, ref object state, ref bool isCompleted)
   at async Task Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.InvokeInnerFilterAsync()+Awaited(?)
   at async Task Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.InvokeNextExceptionFilterAsync()+Awaited(?)

Would it be possible to whip up replacement methods so we can still use this approach? Or is there a better way to accomplish this that doesn't require more coding on your end?

Thanks!

/cc @caldwell0414

@ErikEJ
Copy link
Owner Author

ErikEJ commented Aug 16, 2021

@robertmclaws I am not sure I can see a connection between the EntityConnectionBuilder approach and the call stack. Have you decorated all your DbContext classes with the DbConfigurationType attribute? Apparently that is important.

@ErikEJ
Copy link
Owner Author

ErikEJ commented Aug 16, 2021

@robertmclaws

Except that it appears that EntityConnectionStringBuilder is hard-coded to use System.Data.SqlClient.SqlConnection.

I doubt that is true, I have used it with other providers previously.

@robertmclaws
Copy link

So, does calling DbConfiguration.SetConfiguration(new System.Data.Entity.SqlServer.MicrosoftSqlDbConfiguration()); work, or does it have to be specified as an attribute?

Also, do I need to call DbProviderFactories.RegisterFactory("Microsoft.Data.SqlClient", Microsoft.Data.SqlClient.SqlClientFactory.Instance); too?

Thanks!

@ErikEJ
Copy link
Owner Author

ErikEJ commented Aug 16, 2021

So, does calling DbConfiguration.SetConfiguration(new System.Data.Entity.SqlServer.MicrosoftSqlDbConfiguration()); work, or does it have to be specified as an attribute?

I have not tested that, why dont you try?

Also, do I need to call DbProviderFactories.RegisterFactory("Microsoft.Data.SqlClient", Microsoft.Data.SqlClient.SqlClientFactory.Instance); too?

No:

SetProviderFactory(MicrosoftSqlProviderServices.ProviderInvariantName, Microsoft.Data.SqlClient.SqlClientFactory.Instance);

@ErikEJ
Copy link
Owner Author

ErikEJ commented Aug 16, 2021

The important part is that all DbContexts classes in your solution must be configured to use the new provider...

@jvanderwoude80
Copy link

The important part is that all DbContexts classes in your solution must be configured to use the new provider...

I dug deeper into that. This did fix my issue, however it turned out that while my solution was not using or referencing other DbContext classes, the framework used by the solution did! One database call was performed before my DbContext that needed Microsoft.Data.SqlClient was called. If only this earlier DbContext is configured also to use the new provider or that database call was not performed (commented out) it also works. It even worked when this earlier DbContext call was the only DbContext configured to use the new provider.

Summarizing: only when multiple DbContext classes are used they have to be configured (sctrictly speaking only the first one that is used, but I don't think that is recommended..)

@jvanderwoude80
Copy link

@robertmclaws I'm also using an existing SQL connection the same way you do (using the constructor overload) but not with a connection string builder. I'm using a connection string stored in a keyvault directly. I also don't specify the provider in the SqlConnection, decorating the DbContext class with the configuration is enough to accomplish that. In your code example I don't see the decorator or other way of configuring the provider. I thinks that should do the trick in your case. I do however have some problems with the connection not closing using a SqlConnection this way, but I'm still trying to figure out what the problem is..

@ErikEJ is it possible to override or change the existing configuration when using the decorator? I want to use the SqlAzureExecutionStrategy but when I change the configuration in the constructor by using DbConfiguration.SetConfiguration I get an error an instance of another configuration is already used. Should I then use this way of configuring instead (appending your configuration steps) and drop the decorator?

@ErikEJ
Copy link
Owner Author

ErikEJ commented Aug 17, 2021

@jvanderwoude80 The MicrosoftSqlDbConfiguration class is just a convenience method, you can create your own configuration as you please.

@ErikEJ
Copy link
Owner Author

ErikEJ commented Aug 17, 2021

@robertmclaws Just confirmed that calling

 DbConfiguration.SetConfiguration(new System.Data.Entity.SqlServer.MicrosoftSqlDbConfiguration());

before using any DbContexts works fine.

@robertmclaws
Copy link

Figured it out. FUN FACT: In an EDMX file, the provider type is hard-coded in the edmx:StorageModels/Schema. Doesn't matter what you set it to in code, if you don't fix it there, you're hosed.

@ErikEJ
Copy link
Owner Author

ErikEJ commented Aug 17, 2021

@robertmclaws Good one! Will add to the docs!

@robertmclaws
Copy link

robertmclaws commented Aug 17, 2021

@jvanderwoude80 So I have this class in my codebase now:

using System.Data.Entity;
using System.Data.Entity.SqlServer;

namespace CloudNimble.BurnRate.Data
{

    /// <summary>
    /// 
    /// </summary>
    public class EasyAFSqlAzureConfiguration : DbConfiguration
    {

        private const string MicrosoftDataSqlClient = "Microsoft.Data.SqlClient";

        /// <summary>
        /// 
        /// </summary>
        public EasyAFSqlAzureConfiguration()
        {
            SetProviderFactory(MicrosoftDataSqlClient, Microsoft.Data.SqlClient.SqlClientFactory.Instance);
            SetProviderServices(MicrosoftDataSqlClient, MicrosoftSqlProviderServices.Instance);
            SetExecutionStrategy(MicrosoftDataSqlClient, () => new SqlAzureExecutionStrategy());
        }

    }

}

The first two lines are from @ErikEJ's MicrosoftSqlDbConfiguration class, the last one is from my existing codebase (EasyAF is the name of our app framework).

Then I call it at the very top of my API's Startup.cs:

        public void ConfigureServices(IServiceCollection services)
        {
            DbConfiguration.SetConfiguration(new EasyAFSqlAzureConfiguration());
            //...
        }

I'm NOT using the [DbConfigurationType] attribute, as it was simpler to keep the call I already had, add the other calls, and then fix the provider type in the EDMX.

I have this deployed right now and it seems to be working OK.

@ErikEJ
Copy link
Owner Author

ErikEJ commented Aug 17, 2021

@robertmclaws Thanks, I already updated the readme with that info.
There is a constant in the provider, that you can use for the invariant name, btw.

@jvanderwoude80
Copy link

@robertmclaws thanks. I stumbled on the same approach after some googling, works for me too. I keep however having problems with connection pooling not working on my azure db. Every time a new connection is opened instead of the existing one reused (and that one is not closed) till the limit of the db is reached. Still not sure what causes it. If I have further details I will post it.

@ErikEJ
Copy link
Owner Author

ErikEJ commented Aug 19, 2021

@ionmincu Thanks, I was able to see what was going on now (lack of smoke testing!). Working on a fix!

@ErikEJ
Copy link
Owner Author

ErikEJ commented Aug 19, 2021

@ionmincu Thanks for your testing, this is now fixed in RC5, which everyone watching this should be using!

@ionmincu
Copy link

@ErikEJ thank you, seems to be working now 👍

@ErikEJ
Copy link
Owner Author

ErikEJ commented Aug 23, 2021

@ionmincu @robertmclaws @jvanderwoude80
Can we go to version 1.0.0 RTW with the provider?

@jvanderwoude80
Copy link

@ionmincu @robertmclaws @jvanderwoude80
Can we go to version 1.0.0 RTW with the provider?

As far as I'm concerned, certainly!

@ionmincu
Copy link

I guess so, appears to work in our e2e tests, but, just so you know this purely experimental for our project (for now).

@ErikEJ
Copy link
Owner Author

ErikEJ commented Aug 24, 2021

Thanks, RTW coming up!

@ErikEJ ErikEJ closed this as completed Aug 24, 2021
@robertmclaws
Copy link

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
Copy link
Owner Author

ErikEJ commented Sep 5, 2021

@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
Copy link

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
Copy link
Owner Author

ErikEJ commented Sep 5, 2021

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
Copy link
Owner Author

ErikEJ commented Sep 5, 2021

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

@robertmclaws
Copy link

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
Copy link
Owner Author

ErikEJ commented Sep 5, 2021

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

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

@ErikEJ
Copy link
Owner Author

ErikEJ commented Sep 5, 2021

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: dotnet/SqlClient#836 (comment)

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

@robertmclaws
Copy link

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
Copy link
Owner Author

ErikEJ commented Sep 6, 2021

@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
Copy link

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
Copy link
Owner Author

ErikEJ commented Jan 12, 2022

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
Copy link

eolamisan commented Feb 2, 2022

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
Copy link

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

@eolamisan
Copy link

eolamisan commented Feb 2, 2022

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
Copy link
Owner Author

ErikEJ commented Feb 3, 2022

@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).

Repository owner locked as resolved and limited conversation to collaborators Feb 3, 2022
@ErikEJ
Copy link
Owner Author

ErikEJ commented Feb 3, 2022

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

And that does not work?

@ErikEJ
Copy link
Owner Author

ErikEJ commented Feb 3, 2022

@eolamisan I have created this issue: zzzprojects/EntityFramework-Extensions#467

@ErikEJ
Copy link
Owner Author

ErikEJ commented Aug 9, 2022

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
Copy link
Owner Author

ErikEJ commented Apr 22, 2024

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

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

8 participants