使用Hangfire,Startup.cs中给定的连接字符串throws无法将文件附加为数据库错误



我正在ASP.Net MVC Web应用程序中使用Hangfire,它已经成功安装。我想使用与存储数据相同的LocalDb来存储排队作业,以便Hangfire出列和处理。然而,当我在Startp.cs中提供其在Web.config中定义的connectionString或名称时,我遇到了以下错误。在hangfire之前,我在同一个localDb中添加、删除和更新数据没有遇到任何问题。

Cannot attach the file 'c:usersjerry_devdocumentsvisual studio 2013ProjectsHangfire.HighlighterHangfire.HighlighterApp_Dataaspnet-Hangfire.Highlighter-20150113085546.mdf' as database 'aspnet-Hangfire.Highlighter-20150113085546'.
Startup.cs:
public void Configuration(IAppBuilder app)
        {
            ConfigureAuth(app);
            app.UseHangfire(config =>
            {
                string hangfireConnectionString = @"Data Source=(LocalDb)v11.0;AttachDbFilename=|DataDirectory|aspnet-Hangfire.Highlighter-20150113085546.mdf;Initial Catalog=aspnet-Hangfire.Highlighter-20150113085546;Integrated Security=True";
                config.UseSqlServerStorage(hangfireConnectionString);
                config.UseServer();
            });
        }

我的项目解决方案被命名为"Hangfire.Highlighter">

Web.config:
<connectionStrings>
    <add name="DefaultConnection" connectionString="Data Source=(LocalDb)v11.0;AttachDbFilename=|DataDirectory|aspnet-Hangfire.Highlighter-20150113085546.mdf;Initial Catalog=aspnet-Hangfire.Highlighter-20150113085546;Integrated Security=True" providerName="System.Data.SqlClient" />
</connectionStrings>

我知道这是旧的,但已经9个月了,我也为此感到震惊,并决定在这里写一篇文章。

我的解决方案是只创建一个快速而肮脏的DbContext,将其指向正确的连接字符串,并在构造函数中调用Database.CreateIfNotExists:

public class HangfireContext : DbContext
{
    public HangfireContext() : base("name=HangfireContext")
    {
        Database.SetInitializer<HangfireContext>(null);
        Database.CreateIfNotExists();
    }
}

在HangfireBootstrapper.Start((方法中,我做了如下操作:

public void Start()
{
    lock (_lockObject)
    {
        if (_started) return;
        _started = true;
        HostingEnvironment.RegisterObject(this);
        //This will create the DB if it doesn't exist
        var db = new HangfireContext();
        GlobalConfiguration.Configuration.UseSqlServerStorage("HangfireContext");
       // See the next section on why we set the ServerName
        var options = new BackgroundJobServerOptions()
        {
            ServerName = ConfigurationManager.AppSettings["HangfireServerName"]
        };
        _backgroundJobServer = new BackgroundJobServer(options);
        var jobStarter = DependencyResolver.Current.GetService<JobBootstrapper>();
        //See the Recurring Jobs + SimpleInjector section
        jobStarter.Bootstrap();
    }
}

不知道为什么Hangfire在LocalDb上遇到如此困难——也许它只能处理完整的SQL实例?无论哪种方式,这都适用于我、新的团队成员和新的dev/staining/prod实例。

我也知道这是旧的,但最近遇到了这个。这是我的解决方案:

  1. 在Visual Studio中,转到"查看->SQL Server对象资源管理器">
  2. 如果数据源尚未连接,请连接到该数据源。在上面的示例中,它是"(LocalDb(\v11.0">
  3. 右键单击"数据库"->"添加新数据库">
  4. 填充数据库名称=例如:"aspnet Hangfire.FHighlighter-20150113085546"或您在连接字符串中为数据库命名的任何名称
  5. 填充数据库位置=这应该是应用程序中的数据目录,MVC项目的"App_Data">

这解决了我的问题。

Jack的回答对我不起作用,因为我遇到了这个问题:在应用程序配置文件中找不到名为的连接字符串

我通过以下修改使其工作:

  1. 从基初始值设定项中的字符串中删除"name="。感谢:https://stackoverflow.com/a/37697318/2279059
  2. 这将错误转移到UseSqlServerStorage的调用。因此,我只是从伪数据库上下文中复制连接字符串,而不是将"HangfireContext"传递给它

完整的设置代码:

public class HangfireContext : DbContext
{
    public HangfireContext() : base("HangfireContext")  // Remove "name="
    {
        Database.SetInitializer<HangfireContext>(null);
        Database.CreateIfNotExists();
    }
}
public partial class Startup
{
    public static void ConfigureHangfire(IAppBuilder app)
    {
        var db = new HangfireContext();
        GlobalConfiguration.Configuration.UseSqlServerStorage(db.Database.Connection.ConnectionString);  // Copy connection string
        app.UseHangfireDashboard();
        app.UseHangfireServer();
    }
}

数据库是否已经创建?你能尝试使用不同的连接字符串格式吗?像这样的东西,"服务器=.;数据库=HangFire.Flighter;Trusted_Connection=True;">

根据AspNetCore 3.1和Hangfire 1.7.17 回答

Hangfire应该创建所有表,前提是存在具有指定数据库名称的现有数据库。如果你想使用LocalDb,你可以使用以下注册(见下文(。

services
    .AddHangfire(
        (serviceProvider, config) =>
        {
            //read settings or hardcode connection string, but this is cleaner
            var configuration = serviceProvider.GetService<IConfiguration>();
            var connectionString = configuration.GetValue<string>("Hangfire:ConnectionString");
            var sqlServerStorageOptions =
               new SqlServerStorageOptions
               {
                    CommandBatchMaxTimeout = TimeSpan.FromMinutes(5),
                    SlidingInvisibilityTimeout = TimeSpan.FromMinutes(5),
                    QueuePollInterval = TimeSpan.Zero,
                    UseRecommendedIsolationLevel = true,
                    DisableGlobalLocks = true
               };
            config
                .SetDataCompatibilityLevel(CompatibilityLevel.Version_170)
                .UseSimpleAssemblyNameTypeSerializer()
                .UseRecommendedSerializerSettings();
                .UseSqlServerStorage(connectionString, sqlServerStorageOptions);
        });

在我的例子中,连接字符串是从appsettings中读取的,所以它看起来像这个

"Hangfire": {
  "ConnectionString": "Data Source=(localdb)\MsSqlLocalDb; Database=Hangfire;"
}

再次注意,连接字符串如何具有必须存在于localdb中的数据库的名称(例如:Hangfire(。如果完全删除Database=xxx参数,默认情况下它将选择master数据库并在那里创建所有表。

最新更新