Issue Details (XML | Word | Printable)

Key: DNET-893
Type: Bug Bug
Status: Closed Closed
Resolution: Duplicate
Priority: Major Major
Assignee: Jiri Cincura
Reporter: LC Arch Team
Votes: 0
Watchers: 0
Operations

If you were logged in you would be able to see more operations.
.NET Data provider

Trusted Authentication fails with Code First

Created: 08/Aug/19 09:13 AM   Updated: 08/Aug/19 11:28 AM
Component/s: None
Affects Version/s: 6.7.0.0
Fix Version/s: None

Environment: Windows 10, Firebird Super Server 2.5, Visual Studio 2019, Entity Framework 6.1.3, Code First
Issue Links:
Duplicate
 


 Description  « Hide
*Observed Behavior:
Querying the database via LINQ to entities fails with an InvalidOperationException: No user name was specified.

*Expected Behavior*
No exception

*Cause*
FbProviderServices.GetDbProviderManifestToken creates a new connection through FbServerProperties if the given DbConnection is not already open. FbServerProperties, or more specifically its base classe, FbService does not support Trusted Authentication. FbService.Open specifically checks for the existence of a user name and password and throws an exception.

FbService.cs:
{code}
protected void Open()
{
if (State != FbServiceState.Closed)
throw new InvalidOperationException("Service already Open.");
if (string.IsNullOrEmpty(_csManager.UserID))
throw new InvalidOperationException("No user name was specified.");
if (string.IsNullOrEmpty(_csManager.Password))
throw new InvalidOperationException("No user password was specified.");
{code}

By contrast, FbConnectionInternal first checks for the existence of a user name and password, and branches into trusted authentication. Similar code seems to be missing in FbService.cs.
FbConnectionInternal.cs:
{code}
    public void Connect()
    {
      if (Charset.GetCharset(this.options.Charset) == null)
        throw new FbException("Invalid character set specified");
      try
      {
        this.db = ClientFactory.CreateDatabase(this.options);
        this.db.Charset = Charset.GetCharset(this.options.Charset);
        this.db.Dialect = (short) this.options.Dialect;
        this.db.PacketSize = this.options.PacketSize;
        DatabaseParameterBuffer dpb = this.BuildDpb(this.db, this.options);
        if (this.options.FallIntoTrustedAuth)
          this.db.AttachWithTrustedAuth(dpb, this.options.DataSource, this.options.Port, this.options.Database);
        else
          this.db.Attach(dpb, this.options.DataSource, this.options.Port, this.options.Database);
      }
{code}

*Workaround*
Opening the connection manually before passing it into DbContext is a workaround.

*Stack Trace*
> FirebirdSql.Data.FirebirdClient.dll!FirebirdSql.Data.Services.FbService.Open() Line 108 C#
  FirebirdSql.Data.FirebirdClient.dll!FirebirdSql.Data.Services.FbService.QueryService(byte[] items) Line 346 C#
  FirebirdSql.Data.FirebirdClient.dll!FirebirdSql.Data.Services.FbService.ProcessQuery(byte[] items, System.Action<bool, object> queryResponseAction) Line 235 C#
  FirebirdSql.Data.FirebirdClient.dll!FirebirdSql.Data.Services.FbService.Query(byte[] items) Line 199 C#
  FirebirdSql.Data.FirebirdClient.dll!FirebirdSql.Data.Services.FbServerProperties.GetInfo(int item) Line 87 C#
  FirebirdSql.Data.FirebirdClient.dll!FirebirdSql.Data.Services.FbServerProperties.GetString(int item) Line 77 C#
  EntityFramework.Firebird.dll!FirebirdSql.Data.EntityFramework6.FbProviderServices.GetDbProviderManifestToken(System.Data.Common.DbConnection connection) Line 154 C#
  EntityFramework.dll!System.Data.Entity.Core.Common.DbProviderServices.GetProviderManifestToken(System.Data.Common.DbConnection connection) Unknown
  EntityFramework.dll!System.Data.Entity.Utilities.DbProviderServicesExtensions.GetProviderManifestTokenChecked(System.Data.Entity.Core.Common.DbProviderServices providerServices, System.Data.Common.DbConnection connection) Unknown
  mscorlib.dll!System.Collections.Concurrent.ConcurrentDictionary<System.Tuple<System.Type, string, string>, string>.GetOrAdd(System.Tuple<System.Type, string, string> key, System.Func<System.Tuple<System.Type, string, string>, string> valueFactory) Unknown
  EntityFramework.dll!System.Data.Entity.Utilities.DbConnectionExtensions.GetProviderInfo(System.Data.Common.DbConnection connection, out System.Data.Entity.Core.Common.DbProviderManifest providerManifest) Unknown
  EntityFramework.dll!System.Data.Entity.DbModelBuilder.Build(System.Data.Common.DbConnection providerConnection) Unknown
  EntityFramework.dll!System.Data.Entity.Internal.LazyInternalContext.CreateModel(System.Data.Entity.Internal.LazyInternalContext internalContext) Unknown
  EntityFramework.dll!System.Data.Entity.Internal.RetryLazy<System.Data.Entity.Internal.LazyInternalContext, System.Data.Entity.Infrastructure.DbCompiledModel>.GetValue(System.Data.Entity.Internal.LazyInternalContext input) Unknown
  EntityFramework.dll!System.Data.Entity.Internal.LazyInternalContext.InitializeContext() Unknown
  EntityFramework.dll!System.Data.Entity.Internal.InternalContext.GetEntitySetAndBaseTypeForType(System.Type entityType) Unknown
  EntityFramework.dll!System.Data.Entity.Internal.Linq.InternalSet<Settings.DataAccess.Entities.SettingEntity>.Initialize() Unknown
  EntityFramework.dll!System.Data.Entity.Internal.Linq.InternalSet<Settings.DataAccess.Entities.SettingEntity>.InternalContext.get() Unknown
  EntityFramework.dll!System.Data.Entity.Infrastructure.DbQuery<Settings.DataAccess.Entities.SettingEntity>.System.Linq.IQueryable.Provider.get() Unknown
  System.Core.dll!System.Linq.Queryable.Where<Settings.DataAccess.Entities.SettingEntity>(System.Linq.IQueryable<Settings.DataAccess.Entities.SettingEntity> source, System.Linq.Expressions.Expression<System.Func<Settings.DataAccess.Entities.SettingEntity, bool>> predicate) Unknown

*Connection String*
character set=UTF8;initial catalog=path\to\data.fdb;ServerType=0

 All   Comments   Change History   Subversion Commits      Sort Order: Ascending order - Click to sort in descending order
Jiri Cincura added a comment - 08/Aug/19 09:22 AM
What a great report! Let me create a more generic ticket for this and I'll link those together.

LC Arch Team added a comment - 08/Aug/19 11:13 AM
Thanks for looking into it. Do you see any way to avoid FbProviderServices.GetDbProviderManifestToken from being called by entity framework? In model first, this is apparently read from the SSDL file and entity framework does not call this method at all. Do we have any way to supply this information separately when using code first?

Openening the DbConnection before passing it into DbContext might have impact which we would like to avoid if any way possible.

If you see any way or hints, that would be greatly appreciated!

Jiri Cincura added a comment - 08/Aug/19 11:28 AM
Probably the easiest way is to implement IManifestTokenResolver and use DbConfiguration.SetManifestTokenResolver in configuration. Other option is to (pre)compile the model [http://tracker.firebirdsql.org/browse/DNET-832?focusedCommentId=33973&page=com.atlassian.jira.plugin.system.issuetabpanels%3Acomment-tabpanel#action_33973].