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

时间:2015-01-14 20:48:09

标签: c# asp.net connection-string hangfire

我在ASP .Net MVC Web App中使用Hangfire,它已成功安装。我想使用相同的LocalDb来存储Hangfire的排队作业,以便像我以前用于存储数据一样出列和处理。但是,当我在Web.config中提供Startp.cs中定义的connectionString或名称时,我遇到了以下错误。我在添加时没有遇到任何麻烦,在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>

5 个答案:

答案 0 :(得分:18)

我知道这已经过时了 - 但已经过了9个月了,我也把头发拉了过来 - 然后决定对它进行一次写作here

我的解决方案是创建一个快速而脏的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 / staging / prod实例。

答案 1 :(得分:2)

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

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

答案 2 :(得分:0)

数据库是否已创建?你能尝试使用不同的连接字符串格式吗?这样的话, “服务器= .;数据库= HangFire.Highlighter; Trusted_Connection = TRUE;”

答案 3 :(得分:0)

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

我让它使用以下修改:

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

    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();
        }
    }
    

答案 4 :(得分:0)

根据AspNetCore 3.1和Hangfire 1.7.17的答案

如果有一个具有指定数据库名称的现有数据库,则Hang​​fire应该创建所有表。 如果要使用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数据库并在那里创建所有表。