客户端通过EF和Windows服务

时间:2016-03-29 08:22:50

标签: c# sql-server entity-framework

我有一个Windows C#WPF客户端应用程序,我使用EF来访问LocalDB实例(当然这将是一个真正的SQL Server数据库)。此应用程序使用数据库来保留某些配置​​。最初由EF使用CreateDatabaseIfNotExists初始化程序创建数据库。

然后在启动时自动运行具有本地系统权限的Windows服务。此服务仅在启动时访问数据库,以使用以下代码获取一个特定配置值(从示例代码中删除异常处理,无法使用EF):

using (SqlConnection connection = new SqlConnection
{
    ConnectionString = $"Data Source =(LocalDB)\\MSSQLLocalDB;AttachDbFilename=D:\database.mdf;Integrated Security=True;Connect Timeout=30",
})
{
    connection.Open();
    string query = "SELECT TOP 1 COLUMN_1 FROM TABLE_1;";

    using (SqlCommand command = new SqlCommand(query, connection))
    using (SqlDataReader reader = command.ExecuteReader())
    {
        while (reader.Read())
        {
            if (!reader.IsDBNull(0))
            {
                value = reader.GetString(0);
            }
        }
    }
}

我已多次测试此代码段并在f.e处设置调试断点。 while循环但客户端应用程序总是可以启动并且没有创建数据库的问题(因为它已经存在)。

问题是"它适用于我的机器"并不满足测试人员,因为他们有时会遇到错误,重启后无法再创建数据库。这是异常堆栈跟踪:

  

System.Data.SqlClient.SqlException(0x80131904):无法创建文件' D:\ database.mdf'因为它已经存在更改文件路径或文件名,然后重试该操作。   CREATE DATABASE失败。无法创建列出的某些文件名。检查相关错误。      在System.Data.SqlClient.SqlConnection.OnError(SqlException异常,Boolean breakConnection,Action wrapCloseInAction)      在System.Data.SqlClient.SqlInternalConnection.OnError(SqlException异常,Boolean breakConnection,Action wrapCloseInAction)      在System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning(TdsParserStateObject stateObj,Boolean callerHasConnectionLock,Boolean asyncClose)      在System.Data.SqlClient.TdsParser.TryRun(RunBehavior runBehavior,SqlCommand cmdHandler,SqlDataReader dataStream,BulkCopySimpleResultSet bulkCopyHandler,TdsParserStateObject stateObj,Boolean& dataReady)      在System.Data.SqlClient.SqlCommand.RunExecuteNonQueryTds(String methodName,Boolean async,Int32 timeout,Boolean asyncWrite)      at System.Data.SqlClient.SqlCommand.InternalExecuteNonQuery(TaskCompletionSource completion,String methodName,Boolean sendToPipe,Int32 timeout,Boolean asyncWrite)      在System.Data.SqlClient.SqlCommand.ExecuteNonQuery()      在System.Data.Entity.Infrastructure.Interception.DbCommandDispatcher.b__0(DbCommand t,DbCommandInterceptionContext c)      at System.Data.Entity.Infrastructure.Interception.InternalDispatcher.Dispatch [TTarget,TInterceptionContext,TResult](TTarget target,Func operation,TInterceptionContext interceptionContext,Action execution,Action execution)      在System.Data.Entity.Infrastructure.Interception.DbCommandDispatcher.NonQuery(DbCommand命令,DbCommandInterceptionContext interceptionContext)      在System.Data.Entity.SqlServer.SqlProviderServices。<> c__DisplayClass1a.b__19(DbConnection conn)      在System.Data.Entity.SqlServer.SqlProviderServices。<> c__DisplayClass33.b__32()      在System.Data.Entity.SqlServer.DefaultSqlExecutionStrategy。<> c__DisplayClass1.b__0()      在System.Data.Entity.SqlServer.DefaultSqlExecutionStrategy.Execute [TResult](Func操作)      在System.Data.Entity.SqlServer.DefaultSqlExecutionStrategy.Execute(Action操作)      在System.Data.Entity.SqlServer.SqlProviderServices.UsingConnection(DbConnection sqlConnection,Action act)      在System.Data.Entity.SqlServer.SqlProviderServices.UsingMasterConnection(DbConnection sqlConnection,Action act)      在System.Data.Entity.SqlServer.SqlProviderServices.CreateDatabaseFromScript(Nullable commandTimeout,DbConnection sqlConnection,String createDatabaseScript)      在System.Data.Entity.SqlServer.SqlProviderServices.DbCreateDatabase(DbConnection连接,Nullable commandTimeout,StoreItemCollection storeItemCollection)      在System.Data.Entity.Core.Common.DbProviderServices.CreateDatabase(DbConnection连接,Nullable commandTimeout,StoreItemCollection storeItemCollection)      在System.Data.Entity.Core.Objects.ObjectContext.CreateDatabase()      at System.Data.Entity.Internal.DatabaseOperations.Create(ObjectContext objectContext)      在System.Data.Entity.Internal.DatabaseCreator.CreateDatabase(InternalContext internalContext,Func createMigrator,ObjectContext objectContext)      在System.Data.Entity.Internal.InternalContext.CreateDatabase(ObjectContext objectContext,DatabaseExistenceState existState)      在System.Data.Entity.Database.Create(DatabaseExistenceState existState)      at System.Data.Entity.CreateDatabaseIfNotExists.InitializeDatabase(TContext context)      在System.Data.Entity.Internal.InternalContext。<> c__DisplayClassf`1.b__e()      在System.Data.Entity.Internal.InternalContext.PerformInitializationAction(Action action)      在System.Data.Entity.Internal.InternalContext.PerformDatabaseInitialization()      在System.Data.Entity.Internal.LazyInternalContext.b__4(InternalContext c)      在System.Data.Entity.Internal.RetryAction.PerformAction(TInput输入)      在System.Data.Entity.Internal.LazyInternalContext.InitializeDatabaseAction(Action action)      在System.Data.Entity.Internal.LazyInternalContext.InitializeDatabase()      在System.Data.Entity.Internal.InternalContext.GetEntitySetAndBaseTypeForType(Type entityType)      在System.Data.Entity.Internal.Linq.InternalSet.Initialize()      在System.Data.Entity.Internal.Linq.InternalSet.get_InternalContext()      在System.Data.Entity.Infrastructure.DbQuery.System.Linq.IQueryable.get_Provider()      bei System.Linq.Queryable.Count [TSource](IQueryable source)      bei MyProgram.DatabaseService.Initialize()

我无法解释自己出了什么问题。

可能存在模型不匹配或竞争条件,但我无法让方案重现此错误,说实话,错误消息看起来很简单。

修改

使用procmon检查文件句柄后,您可以看到服务"阻止"数据库文件,只要它使用它加上一些额外的时间(也许SQLLocalDB本身需要这个时间)。 此时没有其他用户可以访问数据库。我尝试使用作为同一用户运行的客户端和服务,然后两者都可以同时访问该文件。怎么会这样?

0 个答案:

没有答案