Asp.net核心rc1,dbcontext连接在IStringLocalizer GetString方法中关闭

时间:2016-03-29 15:11:23

标签: entity-framework localization asp.net-core asp.net-core-mvc

Asp.net核心rc1,dbcontext连接在IStringLocalizer GetString方法中关闭。仅在VS2015处于调试模式时启动,并且仅在启动时启动一次。

我正在使用Autofac DI,但是同样的问题(没有autofac)使用buildin DI。

当我在调试模式下运行应用程序时,仅在启动时,产生以下错误。当我刷新浏览器一切正常,没有错误。如果我在没有调试的情况下运行应用程序,没有错误,一切都正常运行。

调试威胁和DI出了什么问题?有什么想法吗?

浏览器出错:

  

处理请求时数据库操作失败。   InvalidOperationException:ExecuteReader需要打开和   可用连接。连接的当前状态已关闭。

输出窗口:

Microsoft.Data.Entity.Storage.Internal.RelationalCommandBuilderFactory: Information: Executed DbCommand (55ms) [Parameters=[@___cultureName_0='?', @__name_1='?'], CommandType='Text', CommandTimeout='30']
SELECT TOP(1) [l].[CultureId], [l].[Name], [l].[Value]
FROM [UIResources] AS [l]
WHERE ([l].[CultureId] = @___cultureName_0) AND ([l].[Name] = @__name_1)
Microsoft.Data.Entity.Query.Internal.QueryCompiler: Error: An exception occurred in the database while iterating the results of a query.
System.NullReferenceException: Not Specified object reference to an instance object.
   σε System.Data.SqlClient.SqlConnection.TryOpenInner(TaskCompletionSource`1 retry)
   σε System.Data.SqlClient.SqlConnection.TryOpen(TaskCompletionSource`1 retry)
   σε System.Data.SqlClient.SqlConnection.Open()
   σε Microsoft.Data.Entity.Storage.RelationalConnection.Open()
   σε Microsoft.Data.Entity.Query.Internal.QueryingEnumerable.Enumerator.MoveNext()
   σε System.Linq.Enumerable.WhereSelectEnumerableIterator`2.MoveNext()
   σε System.Linq.Enumerable.FirstOrDefault[TSource](IEnumerable`1 source)
   σε lambda_method(Closure , QueryContext )
   σε Microsoft.Data.Entity.Query.Internal.QueryCompiler.<>c__DisplayClass18_1`1.<CompileQuery>b__1(QueryContext qc)
Microsoft.Data.Entity.Query.Internal.QueryCompiler: Error: An exception occurred in the database while iterating the results of a query.
System.InvalidOperationException: ExecuteReader requires an open and available Connection. The connection's current state is closed.
   at System.Data.SqlClient.SqlCommand.ValidateCommand(String method, Boolean async)
   at System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, String method, TaskCompletionSource`1 completion, Int32 timeout, Task& task, Boolean asyncWrite)
   at System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, String method)
   at System.Data.SqlClient.SqlCommand.ExecuteReader(CommandBehavior behavior, String method)
   at Microsoft.Data.Entity.Storage.Internal.RelationalCommand.<>c__DisplayClass17_0.<ExecuteReader>b__0(DbCommand cmd, IRelationalConnection con)
   at Microsoft.Data.Entity.Storage.Internal.RelationalCommand.Execute[T](IRelationalConnection connection, Func`3 action, String executeMethod, Boolean openConnection, Boolean closeConnection)
   at Microsoft.Data.Entity.Storage.Internal.RelationalCommand.ExecuteReader(IRelationalConnection connection, Boolean manageConnection)
   at Microsoft.Data.Entity.Query.Internal.QueryingEnumerable.Enumerator.MoveNext()
   at System.Linq.Enumerable.WhereSelectEnumerableIterator`2.MoveNext()
   at System.Linq.Enumerable.FirstOrDefault[TSource](IEnumerable`1 source)
   at lambda_method(Closure , QueryContext )
   at Microsoft.Data.Entity.Query.Internal.QueryCompiler.<>c__DisplayClass18_1`1.<CompileQuery>b__1(QueryContext qc)
Exception thrown: 'System.NullReferenceException' in EntityFramework.Core.dll
Exception thrown: 'System.InvalidOperationException' in EntityFramework.Core.dll

这是我的创业公司:

public IServiceProvider ConfigureServices(IServiceCollection services)
{
    // Add framework services.
    services.AddEntityFramework()
        .AddSqlServer()
        .AddDbContext<ApplicationDbContext>(options =>
            options.UseSqlServer(Configuration["Data:DefaultConnection:ConnectionString"]));

    services.AddIdentity<ApplicationUser, ApplicationRole>()
        .AddEntityFrameworkStores<ApplicationDbContext>()
        .AddDefaultTokenProviders();

    services.AddMvc().AddViewLocalization();
    services.AddMvc().AddDataAnnotationsLocalization();
    services.AddLocalization();

    // Create the Autofac container builder.
    var builder = new ContainerBuilder();

    // Populate the services from the collection.
    // This have to come First.
    builder.Populate(services);

    // Register dependencies.
    builder.RegisterType<AuthMessageSender>().As<IEmailSender>().InstancePerLifetimeScope();
    builder.RegisterType<AuthMessageSender>().As<ISmsSender>().InstancePerLifetimeScope();
    builder.RegisterType<DataInitializer>().As<IDataInitializer>().InstancePerLifetimeScope();
    builder.RegisterType<CultureHelper>().As<ICultureHelper>().InstancePerLifetimeScope();
    builder.RegisterType<RouteRequestCultureProvider>().InstancePerLifetimeScope();
    builder.RegisterType<CultureActionFilter>().InstancePerLifetimeScope();
    builder.RegisterType<DbStringLocalizerFactory>().As<IStringLocalizerFactory>().InstancePerLifetimeScope();
    // DbStringLocalizer registers with InstancePerDependency, 
    // because localization requires a new instance of IStringLocalizer created in the IStringLocalizerFactory.
    builder.RegisterType<DbStringLocalizer>().As<IStringLocalizer>().InstancePerDependency();

    // Build the container.
    var container = builder.Build();

    // Return the IServiceProvider resolved from the container.
    return container.Resolve<IServiceProvider>();
}

这是本地化实施:

public class DbStringLocalizerFactory : IStringLocalizerFactory
{
    private IServiceProvider _serviceProvider;

    public DbStringLocalizerFactory(IServiceProvider serviceProvider)
    {
        _serviceProvider = serviceProvider;
    }

    public IStringLocalizer Create(Type resourceSource)
    {
        return _serviceProvider.GetService<IStringLocalizer>();
    }

    public IStringLocalizer Create(string baseName, string location)
    {
        return _serviceProvider.GetService<IStringLocalizer>();
    }
}
public class DbStringLocalizer : IStringLocalizer
{
    private ApplicationDbContext _db;
    private string _cultureName;

    public DbStringLocalizer(ApplicationDbContext db)
        : this(db, CultureInfo.CurrentCulture)
    {
    }

    public DbStringLocalizer(ApplicationDbContext db, CultureInfo cultureInfo)
    {
        _db = db;
        _cultureName = cultureInfo.Name;
    }

    public LocalizedString this[string name]
    {
        get
        {
            var value = GetString(name);
            return new LocalizedString(name, value ?? name, resourceNotFound: value == null);
        }
    }

    public LocalizedString this[string name, params object[] arguments]
    {
        get
        {
            var format = GetString(name);
            var value = string.Format(format ?? name, arguments);
            return new LocalizedString(name, value, resourceNotFound: format == null);
        }
    }

    private string GetString(string name)
    {
        //try
        //{
        var query = _db.UIResources.Where(l => l.CultureId == _cultureName);
        var value = query.FirstOrDefault(l => l.Name == name);
        return value?.Value;
        //}
        //catch
        //{
        //    return null;
        //}
    }


    public IEnumerable<LocalizedString> GetAllStrings(bool includeAncestorCultures)
    {
        return _db.UIResources.Where(l => l.CultureId == _cultureName)
            .Select(l => new LocalizedString(l.Name, l.Value, true));
    }

    public IStringLocalizer WithCulture(CultureInfo culture)
    {
        return new DbStringLocalizer(_db, culture);
    }
}

1 个答案:

答案 0 :(得分:0)

IDataInitializer注册为

中的范围服务
builder.RegisterType<DataInitializer>().As<IDataInitializer>().InstancePerLifetimeScope();

看起来很奇怪,因为当应用程序开始确保创建数据库并填充运行应用程序所需的数据或更新后,数据初始化程序只能被调用一次。

我怀疑您在DataInitializer类中的某处放置了作用域数据库上下文,因此在请求期间它变得不可用,因为您的IoC容器将始终在请求期间返回相同的实例。