从Azure Web Job使用Entity Framework更新SQL Azure的正确方法是什么?
我只能找到一个帖子SQL Azure using Azure Web Job
但是上面的解决方案使用SQL Client而不是通过Entity Framework!
可以在Azure Web Job下正确运行代码
public void DoSomething([TimerTrigger("*/5 * * * * *")] TimerInfo timer, TextWriter log)
{
try
{
var tempdetails = _sampleRepository.SearchFor(x=> DateTime.UtcNow > x.DateTo);
foreach (var detail in tempdetails)
{
if (detail.ID == 2)
{
detail.ID = 5;
}
_sampleRepository.Update(detail);
}
_unitOfWork.Commit();
}
catch (Exception ex)
{
log.WriteLine(ex.Message);
}
}
Ninject绑定
public class NinjectBindings : NinjectModule
{
public override void Load()
{
//Register Context
Kernel.Bind<MyDbContext>().ToSelf();
Kernel.Bind<IUnitOfWork<MyDbContext>>().To<UnitOfWork<MyDbContext>>();
//Register Repository
Kernel.Bind(x => x
.FromAssemblyContaining<MyDbContext>()
.SelectAllClasses()
.InheritedFrom(typeof(IRepository<>))
.BindDefaultInterface());
}
}
Program.cs中
static void Main()
{
using (IKernel kernel = new StandardKernel(new NinjectBindings()))
{
var config = new JobHostConfiguration()
{
JobActivator = new NinjectJobActivator(kernel)
};
if (config.IsDevelopment)
{
config.UseDevelopmentSettings();
}
config.UseTimers();
var host = new JobHost(config);
host.RunAndBlock();
}
}
<connectionStrings>
<add name="AzureWebJobsDashboard" connectionString="" />
<add name="AzureWebJobsStorage" connectionString="" />
<add name="EFContext" connectionString="Server=xxxx,1433;Initial Catalog=xxxxxx;....;User
ID=xxxxxxx;Password=xxxxxxxx;...;Encrypt=True;TrustServerCertificate=False;Connection
Timeout=30;App=EntityFramework" providerName="System.Data.SqlClient" /> </connectionStrings>
“用于运行Web作业的Azure门户设置”
正如[MS Support]所讨论的,在我们将AzureWebJobsStorage和AzureWebJobDashboard连接字符串添加为Azure门户中的应用程序设置刀片后,Web作业开始无异常地工作。
如何找出以下问题的根本原因
[工作代码 - 更新数据库]
var tempdetails = _myRepository.SearchFor(condifiotn);
if(tempdetails != null)
{
foreach (var detail in tempdetails)
{
_unitOfWork.GetContext.Entry(detail).State = EntityState.Detached;
//Do Some Modification
detail.Name = "Test";
_unitOfWork.GetContext.Entry(detail).State = EntityState.Modified;
}
//Save Changes
_unitOfWork.Commit();
}
[不工作代码 - 无法更新数据库]
var tempdetails = _myRepository.SearchFor(condifiotn);
if(tempdetails != null)
{
foreach (var detail in tempdetails)
{
//Do Some Modification
detail.Name = "Test";
_myRepository.Update(detail);
}
//Save Changes
_unitOfWork.Commit();
}
更新方法
public void Update(E entity)
{
//_dbSet.Attach(entity);
UnitOfWork.GetContext.Entry(entity).State = System.Data.Entity.EntityState.Modified;
}
根据你的描述,我按照这个tutorial在我的Azure Web作业中实现我的存储库和工作单元模式。您可以按照下面的代码段检查您的代码。
NinjectBindings:
public class NinjectBindings : Ninject.Modules.NinjectModule
{
public override void Load()
{
Bind<DbContext>().ToMethod(ctx=> {
return new BruceDbContext();
});
Bind<IUnitOfWork>().To<UnitOfWork>();
}
}
BruceDbContext:
public class BruceDbContext : DbContext
{
public BruceDbContext()
: base("name=brucedbcontext")
{
}
public BruceDbContext(string nameOrConnectionString) : base(nameOrConnectionString)
{
}
//...
}
的UnitOfWork:
public class UnitOfWork : IUnitOfWork
{
private readonly DbContext _dbContext;
public UnitOfWork(DbContext dbContext)
{
_dbContext = dbContext;
}
public IRepository<Author> AuthorRepository =>
new GenericRepository<Author>(_dbContext);
public void SaveChanges()
{
_dbContext.SaveChanges();
}
public void Dispose()
{
_dbContext.Dispose();
}
}
Functions.cs
public class Functions
{
private static IUnitOfWork _iUnitOfWork;
public Functions(IUnitOfWork iUnitOfWork)
{
_iUnitOfWork = iUnitOfWork;
}
public void DoSomething([TimerTrigger("*/30 * * * * *")] TimerInfo timer, TextWriter log)
{
_iUnitOfWork.AuthorRepository.Add(new Author()
{
Name = Guid.NewGuid().ToString()
});
_iUnitOfWork.Commit();
var allRecords=_iUnitOfWork.AuthorRepository.GetAll().ToList();
Console.WriteLine(JsonConvert.SerializeObject(allRecords));
}
}
注意:由于您使用的是TimerTrigger
,因此在构造config.UseTimers();
之前需要调用JobHost
。此外,您可以在本地调试您的webjob以查找详细错误。或者您可以更新您的问题并提供更详细的错误(例如ex.StackTrace),以便我们缩小此问题的范围。
在Singleton Scope
的Ninject绑定做了例外。我知道这不是最好的解决方案。等待最好的ans。如果我在调用范围中配置Ninject的一些方法。
//注册上下文
Kernel.Bind<MyDbContext>().ToSelf().InSingletonScope();
Kernel.Bind<IUnitOfWork<MyDbContext>>().To<UnitOfWork<MyDbContext>>().InSingletonScope();
[使用InSingletonScope
波纹管代码按预期工作]
var tempdetails = _myRepository.SearchFor(condifiotn);
if(tempdetails != null)
{
foreach (var detail in tempdetails)
{
//Do Some Modification
detail.Name = "Test";
_myRepository.Update(detail);
}
//Save Changes
_unitOfWork.Commit();
}