11

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

Cannot attach the file 'c:\users\jerry_dev\documents\visual studio 2013\Projects\Hangfire.Highlighter\Hangfire.Highlighter\App_Data\aspnet-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>
4

5 回答 5

21

我知道这已经过时了——但已经 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 实例?无论哪种方式,这对我、新团队成员和新的开发/登台/生产实例都有效。

于 2015-08-30T02:20:54.193 回答
4

我也知道这是旧的,但最近遇到了这个。这是我的修复:

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

这解决了我的问题。

于 2015-12-21T20:42:35.923 回答
2

杰克的回答对我不起作用,因为我遇到了这个问题:No connection string named could be found in the application config file

我让它与以下修改一起工作:

  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();
    }
}
于 2017-02-08T18:13:41.690 回答
0

数据库是否已经创建?您可以尝试使用不同的连接字符串格式吗?像这样,“Server=.;Database=HangFire.Highlighter;Trusted_Connection=True;”

于 2015-01-16T14:56:38.273 回答
0

根据 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;"
}

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

于 2020-11-03T16:07:46.240 回答