使用SQL CE的{ABP Boilerplate

时间:2018-02-20 10:38:03

标签: sql-server-ce aspnetboilerplate asp.net-boilerplate

我有一个使用EntityFramework和SQL Server EF DB的简单ASP.NET应用程序。

问题是,如果我尝试使用SQL CE(精简版),我的应用程序服务会在第二次调用存储库时抛出异常,并显示错误:

ExecuteReader需要一个开放且可用的连接

如果我返回SQL Express数据库,则所有工作都成功。

这里是我使用的步骤和代码:

修改客户端应用程序App.config文件(我只报告更改):

<!-- language: lang-xml -->
<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <configSections>
    <section name="entityFramework" .../>
  </configSections>
  <connectionStrings>
    <add name="Default" providerName="System.Data.SqlServerCe.4.0" connectionString="Data Source=C:\temp\Deeds.sdf" />**
  </connectionStrings>
  ...
  <entityFramework>
    <defaultConnectionFactory type="System.Data.Entity.Infrastructure.SqlCeConnectionFactory, EntityFramework">
      <parameters>
        <parameter value="System.Data.SqlServerCe.4.0" />
      </parameters>
    </defaultConnectionFactory>
    <providers>
      <provider invariantName="System.Data.SqlClient" type="System.Data.Entity.SqlServer.SqlProviderServices, EntityFramework.SqlServer" />
      <provider invariantName="System.Data.SqlServerCe.4.0" type="System.Data.Entity.SqlServerCompact.SqlCeProviderServices, EntityFramework.SqlServerCompact" />
    </providers>
  </entityFramework>
  <system.data>
    <DbProviderFactories>
      <remove invariant="System.Data.SqlServerCe.4.0" />
      <add name="Microsoft SQL Server Compact Data Provider 4.0" invariant="System.Data.SqlServerCe.4.0" description=".NET Framework Data Provider for Microsoft SQL Server Compact" type="System.Data.SqlServerCe.SqlCeProviderFactory, System.Data.SqlServerCe, Version=4.0.0.0, Culture=neutral, PublicKeyToken=89845dcd8080cc91" />
    </DbProviderFactories>
  </system.data>
  ...
</configuration>

他们必须设置UOW的隔离级别:

public class DeedsWinFormEFModule : AbpModule {

    public override void PreInitialize() {
        Configuration.UnitOfWork.IsolationLevel = System.Transactions.IsolationLevel.ReadCommitted;
    }

    public override void Initialize() {
        IocManager.RegisterAssemblyByConvention(Assembly.GetExecutingAssembly());
    }
}

但在我的ApplicationService中,此方法在第二个数据库查询

时失败
public class DeedImmobileAppService
    : DeedsAppServiceBase, IDeedImmobileAppService {

    protected readonly IRepository<CfgBase100Repo> _cfgBase100Repo;
    protected readonly IRepository<CfgCasa> _cfgCasaRepo;

...

    public async Task<IReadOnlyList<DeedEntryDto>> CalculateValuesForEntries(UpdateDefaultEntriesRequest input) {
        var tipoCasa = await _cfgCasaRepo.FirstOrDefaultAsync(input.HouseTypeId);
        var base100 = await _cfgBase100Repo.FirstOrDefaultAsync(cfg => (cfg.MinDeedRange <= input.DeedValue) && (input.DeedValue < cfg.MaxDeedRange));
        ...
        return list;
    }
}

第二次调用存储库始终失败(var tipoCasa = ...):

    var base100 = await _cfgBase100Repo.FirstOrDefaultAsync(cfg => (cfg.MinDeedRange <= input.DeedValue) && (input.DeedValue < cfg.MaxDeedRange));
    var tipoCasa = await _cfgCasaRepo.FirstOrDefaultAsync(input.HouseTypeId);

我也试图反转线条。在这种情况下var base100 =失败:

    var tipoCasa = await _cfgCasaRepo.FirstOrDefaultAsync(input.HouseTypeId);
    var base100 = await _cfgBase100Repo.FirstOrDefaultAsync(cfg => (cfg.MinDeedRange <= input.DeedValue) && (input.DeedValue < cfg.MaxDeedRange));

我收到的错误是:

Inner Exception 1:
EntityCommandExecutionException: An error occurred while executing the command definition. See the inner exception for details.

Inner Exception 2:
InvalidOperationException: ExecuteReader requires an open and available Connection. The connection's current state is Closed.

此处是堆栈跟踪:

  

System.Reflection.TargetInvocationException HResult = 0x80131604
  Message =调用目标抛出了异常   Source = mscorlib StackTrace:at   System.RuntimeMethodHandle.InvokeMethod(Object target,Object []   参数,签名sig,布尔构造函数)at   System.Reflection.RuntimeMethodInfo.UnsafeInvokeInternal(Object obj,   Object []参数,Object []参数)at   System.Delegate.DynamicInvokeImpl(Object [] args)at   System.Windows.Forms.Control.InvokeMarshaledCallbackDo(ThreadMethodEntry   tme)at   System.Windows.Forms.Control.InvokeMarshaledCallbackHelper(Object obj)   在System.Threading.ExecutionContext.RunInternal(ExecutionContext   executionContext,ContextCallback回调,对象状态,布尔值   preserveSyncCtx)at   System.Threading.ExecutionContext.Run(执行上下文   executionContext,ContextCallback回调,对象状态,布尔值   preserveSyncCtx)at   System.Threading.ExecutionContext.Run(执行上下文   executionContext,ContextCallback回调,对象状态)at   System.Windows.Forms.Control.InvokeMarshaledCallback(ThreadMethodEntry   tme)在System.Windows.Forms.Control.InvokeMarshaledCallbacks()
  在System.Windows.Forms.Control.WndProc(Message&amp; m)at   System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message&amp; m)   在System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message&amp;   m)在System.Windows.Forms.NativeWindow.DebuggableCallback(IntPtr)   hWnd,Int32 msg,IntPtr wparam,IntPtr lparam)at   System.Windows.Forms.UnsafeNativeMethods.DispatchMessageW(MSG&amp; msg)
  在   System.Windows.Forms.Application.ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop(IntPtr的   dwComponentID,Int32 reason,Int32 pvLoopData)at   System.Windows.Forms.Application.ThreadContext.RunMessageLoopInner(的Int32   reason,ApplicationContext context)at   System.Windows.Forms.Application.ThreadContext.RunMessageLoop(的Int32   reason,ApplicationContext context)at   System.Windows.Forms.Application.Run(Form mainForm)at   GPSoftware.Deeds.WinForm.Program.Main()in   C:\ WA \ GPse \ NotuleNotai \ Notule \ Deeds.WinForm \ Program.cs:第34行

内部异常1:

  

EntityCommandExecutionException:执行时发生错误   命令定义。有关详细信息,请参阅内部异常。

内部异常2:

  

InvalidOperationException:ExecuteReader需要打开和   可用连接。连接的当前状态为Closed。

1 个答案:

答案 0 :(得分:1)

我不确定这是正确的解决方案,但我通过标记UOW而不是交易解决了这个问题:

[DependsOn(
    typeof(DeedsDataModule),
    typeof(DeedsApplicationModule))]
public class DeedsWinFormEFModule : AbpModule {

    public override void PreInitialize() {
        // Configuration.UnitOfWork.IsolationLevel = System.Transactions.IsolationLevel.ReadCommitted;  // <= this is not needed!
        Configuration.UnitOfWork.IsTransactional = false; // <= solution!
    }

    public override void Initialize() {
        IocManager.RegisterAssemblyByConvention(Assembly.GetExecutingAssembly());
    }
}

<强>更新

这是正确的解决方案:EF不支持SQL CE事务,因为当使用带有Code First的SQL CE并且SQL CE不支持分布式事务时, TransactionScope 会导致升级到分布式事务