我正在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实例。
我也知道这是旧的,但最近遇到了这个。这是我的解决方案:
- 在Visual Studio中,转到"查看->SQL Server对象资源管理器">
- 如果数据源尚未连接,请连接到该数据源。在上面的示例中,它是"(LocalDb(\v11.0">
- 右键单击"数据库"->"添加新数据库">
- 填充数据库名称=例如:"aspnet Hangfire.FHighlighter-20150113085546"或您在连接字符串中为数据库命名的任何名称
- 填充数据库位置=这应该是应用程序中的数据目录,MVC项目的"App_Data">
这解决了我的问题。
Jack的回答对我不起作用,因为我遇到了这个问题:在应用程序配置文件中找不到名为的连接字符串
我通过以下修改使其工作:
- 从基初始值设定项中的字符串中删除
"name="
。感谢:https://stackoverflow.com/a/37697318/2279059 - 这将错误转移到
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数据库并在那里创建所有表。