Why can't I see a localdb database created by

2019-02-22 10:46发布

Does UWP support LocalDB?
My investigations indicate there are some issues using localdb that I don't experience with SQL Server 2017 Development edition.

I managed to convert a winforms EF-Code First, xaf application to run as a UWP app with the help of this blog

I have Enterprise Authentication set.

When I run the desktop bridge app it creates the database and log file inside

c:\users\kirst

which is my user folder.

However I cannot see the new database in the SQL Server Object Explorer

Clicking Refresh does not help.

A similar app that does not use the desktop bridge will also create the database inside my user directory. In this case I can also see the database in the SQL Server Object Explorer , (localdb)\MSSQLLocalDB

In both cases the connection string is of the form

"Integrated Security=SSPI;MultipleActiveResultSets=True;Data Source=(localdb)\mssqllocaldb;Initial Catalog=mydatabase" 

and

providerName="System.Data.SqlClient"/>

I am using Entity Framework 6.2

.Net Framework 4.7.2

UWP Target Version and Min Version 1809 Build 17763

I am running in the VS2017 15.9.4 IDE

At a dos prompt in c:\Program files\Microsoft SQL Server

dir sqlservr.exe /s shows 2 files

one at

c:\Program files\Microsoft SQL Server\130\LocalDB\Binn

and one at

c:\Program files\Microsoft SQL Server\MSSQL14.MSSQLSERVER\MSSQL\Binn

When I query @@Version from within the program, in both cases I see

Microsoft SQL Server 2016 (SP1) (KB3182545) - 13.0.4001.0 (X64)   
Oct 28 2016 18:17:30   Copyright (c) Microsoft Corporation  
Express Edition (64-bit) on Windows 10 Pro 6.3 <X64> 
(Build 17763: ) (Hypervisor)

I experience problems if I try to connect to the database created by my UWP App from my non UWP Program

For example this message about a log file in a folder that does not exist.

missing file

This issue is linked

[Update1]

I set up a simple demo of the problem on Github

Set the Startup project to WAPProjThings (The Desktop Bridge) to run it.

In the demo ,if I create the database via the Bridge App as startup then switch to the console app to run, I get

An unhandled exception of type 'System.Data.SqlClient.SqlException' occurred in EntityFramework.dll
Additional information: Cannot create file 'C:\Users\kirst\Things02.mdf' because it already exists. Change the file path or the file name, and retry the operation.
CREATE DATABASE failed. Some file names listed could not be created. Check related errors. occurred

If I create the database using the Console App and then try and open it with the Bridge app the error is

`System.Data.SqlClient.SqlException
  HResult=0x80131904
  Message=Cannot create file 'C:\Users\kirst\Things03.mdf' because it already exists. Change the file path or the file name, and retry the operation.
CREATE DATABASE failed. Some file names listed could not be created. Check related errors.
  Source=.Net SqlClient Data Provider
  StackTrace:
   at System.Data.SqlClient.SqlConnection.OnError(SqlException exception, Boolean breakConnection, Action`1 wrapCloseInAction)
   at System.Data.SqlClient.SqlInternalConnection.OnError(SqlException exception, Boolean breakConnection, Action`1 wrapCloseInAction)
   at System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning(TdsParserStateObject stateObj, Boolean callerHasConnectionLock, Boolean asyncClose)
   at System.Data.SqlClient.TdsParser.TryRun(RunBehavior runBehavior, SqlCommand cmdHandler, SqlDataReader dataStream, BulkCopySimpleResultSet bulkCopyHandler, TdsParserStateObject stateObj, Boolean& dataReady)
   at System.Data.SqlClient.SqlCommand.RunExecuteNonQueryTds(String methodName, Boolean async, Int32 timeout, Boolean asyncWrite)
   at System.Data.SqlClient.SqlCommand.InternalExecuteNonQuery(TaskCompletionSource`1 completion, String methodName, Boolean sendToPipe, Int32 timeout, Boolean& usedCache, Boolean asyncWrite, Boolean inRetry)
   at System.Data.SqlClient.SqlCommand.ExecuteNonQuery()
   at System.Data.Entity.Infrastructure.Interception.DbCommandDispatcher.<NonQuery>b__0(DbCommand t, DbCommandInterceptionContext`1 c)
   at System.Data.Entity.Infrastructure.Interception.InternalDispatcher`1.Dispatch[TTarget,TInterceptionContext,TResult](TTarget target, Func`3 operation, TInterceptionContext interceptionContext, Action`3 executing, Action`3 executed)
   at System.Data.Entity.Infrastructure.Interception.DbCommandDispatcher.NonQuery(DbCommand command, DbCommandInterceptionContext interceptionContext)
   at System.Data.Entity.SqlServer.SqlProviderServices.<>c__DisplayClass1a.<CreateDatabaseFromScript>b__19(DbConnection conn)
   at System.Data.Entity.SqlServer.SqlProviderServices.<>c__DisplayClass33.<UsingConnection>b__32()
   at System.Data.Entity.SqlServer.DefaultSqlExecutionStrategy.<>c__DisplayClass1.<Execute>b__0()
   at System.Data.Entity.SqlServer.DefaultSqlExecutionStrategy.Execute[TResult](Func`1 operation)
   at System.Data.Entity.SqlServer.DefaultSqlExecutionStrategy.Execute(Action operation)
   at System.Data.Entity.SqlServer.SqlProviderServices.UsingConnection(DbConnection sqlConnection, Action`1 act)
   at System.Data.Entity.SqlServer.SqlProviderServices.UsingMasterConnection(DbConnection sqlConnection, Action`1 act)
   at System.Data.Entity.SqlServer.SqlProviderServices.CreateDatabaseFromScript(Nullable`1 commandTimeout, DbConnection sqlConnection, String createDatabaseScript)
   at System.Data.Entity.SqlServer.SqlProviderServices.DbCreateDatabase(DbConnection connection, Nullable`1 commandTimeout, StoreItemCollection storeItemCollection)
   at System.Data.Entity.Core.Common.DbProviderServices.CreateDatabase(DbConnection connection, Nullable`1 commandTimeout, StoreItemCollection storeItemCollection)
   at System.Data.Entity.Core.Objects.ObjectContext.CreateDatabase()
   at System.Data.Entity.Migrations.Utilities.DatabaseCreator.Create(DbConnection connection)
   at System.Data.Entity.Migrations.DbMigrator.EnsureDatabaseExists(Action mustSucceedToKeepDatabase)
   at System.Data.Entity.Migrations.DbMigrator.Update(String targetMigration)
   at System.Data.Entity.Internal.DatabaseCreator.CreateDatabase(InternalContext internalContext, Func`3 createMigrator, ObjectContext objectContext)
   at System.Data.Entity.Internal.InternalContext.CreateDatabase(ObjectContext objectContext, DatabaseExistenceState existenceState)
   at System.Data.Entity.Database.Create(DatabaseExistenceState existenceState)
   at System.Data.Entity.CreateDatabaseIfNotExists`1.InitializeDatabase(TContext context)
   at System.Data.Entity.Internal.InternalContext.<>c__DisplayClassf`1.<CreateInitializationAction>b__e()
   at System.Data.Entity.Internal.InternalContext.PerformInitializationAction(Action action)
   at System.Data.Entity.Internal.InternalContext.PerformDatabaseInitialization()
   at System.Data.Entity.Internal.LazyInternalContext.<InitializeDatabase>b__4(InternalContext c)
   at System.Data.Entity.Internal.RetryAction`1.PerformAction(TInput input)
   at System.Data.Entity.Internal.LazyInternalContext.InitializeDatabaseAction(Action`1 action)
   at System.Data.Entity.Internal.LazyInternalContext.InitializeDatabase()
   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.get_InternalContext()
   at System.Data.Entity.Infrastructure.DbQuery`1.System.Linq.IQueryable.get_Provider()
   at System.Linq.Queryable.FirstOrDefault[TSource](IQueryable`1 source)
   at ClassLibrary2.ThingFuncs.ThingDo() in C:\dev\Things\ClassLibrary2\ThingFuncs.cs:line 11
   at Things.Form1.Form1_Load(Object sender, EventArgs e) in C:\dev\Things\Things\Form1.cs:line 23
   at System.Windows.Forms.Form.OnLoad(EventArgs e)
   at System.Windows.Forms.Form.OnCreateControl()
   at System.Windows.Forms.Control.CreateControl(Boolean fIgnoreVisible)
   at System.Windows.Forms.Control.CreateControl()
   at System.Windows.Forms.Control.WmShowWindow(Message& m)
   at System.Windows.Forms.Control.WndProc(Message& m)
   at System.Windows.Forms.ScrollableControl.WndProc(Message& m)
   at System.Windows.Forms.Form.WmShowWindow(Message& m)
   at System.Windows.Forms.Form.WndProc(Message& m)
   at System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m)
   at System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m)
   at System.Windows.Forms.NativeWindow.DebuggableCallback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)
`I 

[Update2]

I tried to investigate whether a new UWP app - non desktop bridge had the same issue. To do this I created a solution containing UWP app and a Framework 4.7.2 library. Nuget let me add Entity Framework 6.2 to both projects. However when I tried to add a reference the library from the UWP I got a message

Unable to add a reference to project

unable to add

followed by

The method or operation is not implemented

the method or operation

Then I got the Warning

Warning NU1701  Package 'EntityFramework 6.2.0' was restored using '.NETFramework,Version=v4.6.1'
instead of the project target framework 'UAP,Version=v10.0.17134'. 
This package may not be fully compatible with your project. App1    C:\dev\XThings2\App1\App1.csproj

[Update3]

I created a new UWP App with a UWP Class library to hold an Entity Framework Core Data Access layer.

However when I tried to run that I got an error indicating that

LocalDB is not supported on this platform.

    System.PlatformNotSupportedException: LocalDB is not supported on this platform.
   at System.Data.SqlClient.SNI.LocalDB.GetLocalDBConnectionString(String localDbInstance)
   at System.Data.SqlClient.SNI.SNIProxy.GetLocalDBDataSource(String fullServerName, Boolean& error)
   at System.Data.SqlClient.SNI.SNIProxy.CreateConnectionHandle(Object callbackObject, String fullServerName, Boolean ignoreSniOpenTimeout, Int64 timerExpire, Byte[]& instanceName, Byte[]& spnBuffer, Boolean flushCache, Boolean async, Boolean parallel, Boolean isIntegratedSecurity)
   at System.Data.SqlClient.SNI.TdsParserStateObjectManaged.CreatePhysicalSNIHandle(String serverName, Boolean ignoreSniOpenTimeout, Int64 timerExpire, Byte[]& instanceName, Byte[]& spnBuffer, Boolean flushCache, Boolean async, Boolean parallel, Boolean isIntegratedSecurity)
   at System.Data.SqlClient.TdsParser.Connect(ServerInfo serverInfo, SqlInternalConnectionTds connHandler, Boolean ignoreSniOpenTimeout, Int64 timerExpire, Boolean encrypt, Boolean trustServerCert, Boolean integratedSecurity, Boolean withFailover)
   at System.Data.SqlClient.SqlInternalConnectionTds.AttemptOneLogin(ServerInfo serverInfo, String newPassword, SecureString newSecurePassword, Boolean ignoreSniOpenTimeout, TimeoutTimer timeout, Boolean withFailover)
   at System.Data.SqlClient.SqlInternalConnectionTds.LoginNoFailover(ServerInfo serverInfo, String newPassword, SecureString newSecurePassword, Boolean redirectedUserInstance, SqlConnectionString connectionOptions, SqlCredential credential, TimeoutTimer timeout)
   at System.Data.SqlClient.SqlInternalConnectionTds.OpenLoginEnlist(TimeoutTimer timeout, SqlConnectionString connectionOptions, SqlCredential credential, String newPassword, SecureString newSecurePassword, Boolean redirectedUserInstance)
   at System.Data.SqlClient.SqlInternalConnectionTds..ctor(DbConnectionPoolIdentity identity, SqlConnectionString connectionOptions, SqlCredential credential, Object providerInfo, String newPassword, SecureString newSecurePassword, Boolean redirectedUserInstance, SqlConnectionString userConnectionOptions, SessionData reconnectSessionData, Boolean applyTransientFaultHandling, String accessToken)
   at System.Data.SqlClient.SqlConnectionFactory.CreateConnection(DbConnectionOptions options, DbConnectionPoolKey poolKey, Object poolGroupProviderInfo, DbConnectionPool pool, DbConnection owningConnection, DbConnectionOptions userOptions)
   at System.Data.ProviderBase.DbConnectionFactory.CreatePooledConnection(DbConnectionPool pool, DbConnection owningObject, DbConnectionOptions options, DbConnectionPoolKey poolKey, DbConnectionOptions userOptions)
   at System.Data.ProviderBase.DbConnectionPool.CreateObject(DbConnection owningObject, DbConnectionOptions userOptions, DbConnectionInternal oldConnection)
   at System.Data.ProviderBase.DbConnectionPool.UserCreateRequest(DbConnection owningObject, DbConnectionOptions userOptions, DbConnectionInternal oldConnection)
   at System.Data.ProviderBase.DbConnectionPool.TryGetConnection(DbConnection owningObject, UInt32 waitForMultipleObjectsTimeout, Boolean allowCreate, Boolean onlyOneCheckConnection, DbConnectionOptions userOptions, DbConnectionInternal& connection)
   at System.Data.ProviderBase.DbConnectionPool.TryGetConnection(DbConnection owningObject, TaskCompletionSource`1 retry, DbConnectionOptions userOptions, DbConnectionInternal& connection)
   at System.Data.ProviderBase.DbConnectionFactory.TryGetConnection(DbConnection owningConnection, TaskCompletionSource`1 retry, DbConnectionOptions userOptions, DbConnectionInternal oldConnection, DbConnectionInternal& connection)
   at System.Data.ProviderBase.DbConnectionInternal.TryOpenConnectionInternal(DbConnection outerConnection, DbConnectionFactory connectionFactory, TaskCompletionSource`1 retry, DbConnectionOptions userOptions)
   at System.Data.ProviderBase.DbConnectionClosed.TryOpenConnection(DbConnection outerConnection, DbConnectionFactory connectionFactory, TaskCompletionSource`1 retry, DbConnectionOptions userOptions)
   at System.Data.SqlClient.SqlConnection.TryOpen(TaskCompletionSource`1 retry)
   at System.Data.SqlClient.SqlConnection.Open()
   at Microsoft.EntityFrameworkCore.Storage.RelationalConnection.OpenDbConnection(Boolean errorsExpected)
   at Microsoft.EntityFrameworkCore.Storage.RelationalConnection.Open(Boolean errorsExpected)
   at Microsoft.EntityFrameworkCore.Storage.RelationalConnection.BeginTransaction(IsolationLevel isolationLevel)
   at Microsoft.EntityFrameworkCore.Storage.RelationalConnection.BeginTransaction()
   at Microsoft.EntityFrameworkCore.Update.Internal.BatchExecutor.Execute(DbContext _, ValueTuple`2 parameters)
   at Microsoft.EntityFrameworkCore.SqlServer.Storage.Internal.SqlServerExecutionStrategy.Execute[TState,TResult](TState state, Func`3 operation, Func`3 verifySucceeded)
   at Microsoft.EntityFrameworkCore.Update.Internal.BatchExecutor.Execute(IEnumerable`1 commandBatches, IRelationalConnection connection)
   at Microsoft.EntityFrameworkCore.Storage.RelationalDatabase.SaveChanges(IReadOnlyList`1 entries)
   at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.StateManager.SaveChanges(IReadOnlyList`1 entriesToSave)
   at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.StateManager.SaveChanges(Boolean acceptAllChangesOnSuccess)
   at Microsoft.EntityFrameworkCore.DbContext.SaveChanges(Boolean acceptAllChangesOnSuccess)
   at Microsoft.EntityFrameworkCore.DbContext.SaveChanges()
   at Data.ThingFuncs.ThingDo()

[Update4]

Back in my original program I have discovered that create database behaviour of the UWP app is different when running in release mode to running in debug mode.

When running in Release Mode via the Bridge Project CheckDatabaseCompatibility does not trigger the xaf DatabaseVersionMismatch event. When running in Release mode in the console project it does. ( This particular behavior occurs for SQL Server Developer edition as well ) Possibly I should write it up as a separate question, but I mention it here in case it is linked.

2条回答
劳资没心,怎么记你
2楼-- · 2019-02-22 11:18

I have come to the conclusion that localdb is not a supported version of SQL Server for production.

As explained here

LocalDB is a special, low impact version of the SQL Server engine, that is not installed as a Windows Service, but launched (made to run) on demand by the ADO.NET client opening a connection to it. It is intended for single user scenarios, and not for any prodcution use - for production you should use SQL Server Express (or higher)

查看更多
爷、活的狠高调
3楼-- · 2019-02-22 11:28

There is a method to connect UWP to a localdb, you have to use the winforms sql data factory method the issues is although you have access to System.Data.SQLClient, you do not have SqlDataAdapter so you cannot create a user login system. However you can read data from the database and create ObservableCollections. To save you time Adapter Client doesn't work either. I think we have to wait for another update where the all the SQL libraries have been added.

查看更多
登录 后发表回答