我有一个非常奇怪的问题 - 有时我的数据库无法填充计划和存储桶,然后在尝试将任务保存到数据库时抛出最后显示的异常。其他时候代码完美无缺。我很感激任何有关为什么这样做的见解。这可能是删除命令的计时问题吗?
EntitiesModelContainer db = new EntitiesModelContainer();
List<Plan> ignoredPlans = db.Plans.Where(p => p.Ignore).ToList();
// Delete old data completely
// foreign keys will cascade delete some tables such as buckets and tasks
db.Database.ExecuteSqlCommand("DELETE FROM Plans");
db.Database.ExecuteSqlCommand("DELETE FROM Assignees");
PlansResponse plans = GraphAPI.GetPlans();
foreach (PlanResponse plan in plans.Plans)
{
Plan planRecord = new Plan()
{
Id = plan.ID,
Title = plan.Title,
Ignore = ignoredPlans.Find(p => p.Id == plan.ID) != null
};
db.Plans.Add(planRecord);
bool changes = db.ChangeTracker.HasChanges();
int result = db.SaveChanges();
if (!planRecord.Ignore)
{
BucketsResponse buckets = GraphAPI.GetBuckets(plan);
foreach (BucketResponse bucket in buckets.Buckets)
{
Bucket bucketRecord = new Bucket()
{
Id = bucket.ID,
Name = bucket.Name,
PlanId = bucket.PlanID
};
db.Buckets.Add(bucketRecord);
db.SaveChanges();
}
TasksResponse tasks = GraphAPI.GetTasks(plan);
foreach (TaskResponse task in tasks.Tasks)
{
Task taskRecord = new Task()
{
Id = task.ID,
Title = task.Title,
Progress = task.PercentComplete,
Description = task.HasDescription ? GraphAPI.GetTaskDetails(task).Description : null,
CreatedDateTime = task.CreatedDateTime,
DueDateTime = task.DueDateTime,
CompletedDateTime = task.CompletedDateTime,
PlanId = task.PlanID,
BucketId = task.BucketID
};
db.Tasks.Add(taskRecord);
db.SaveChanges();
最后一行是发生错误的地方。
SqlException:INSERT语句与FOREIGN KEY约束“FK_PlanTask”冲突。冲突发生在数据库“Dashboard-dev”,表“dbo.Plans”,列“Id”中。声明已经终止。
奇怪的是,它并不总是扔!任何帮助将不胜感激。
更新:你说得对 - 看起来代码同时运行了两次。为什么?我没有(故意)意味着这样做......
public class DBController : Controller
{
public ActionResult Index()
{
DBAccess.UpdateData();
return View();
}
}
上面发布的代码段是此方法UpdateData()
的开头。
答案 0 :(得分:2)
由于它抱怨外键PlanId(我猜),我会说GetTasks以某种方式返回错误的PlanId。
要了解它的底部,我将设置一个探查器会话,并在出现错误时检查SQL语句。或者只是在异常发生时检查调试器中的对象,我猜。属性的值应该给出了发生了什么的线索。
编辑:我刚注意到你的第一行说'有时它没有填充计划和任务',错过了。我不明白如果它无法保存计划会如何继续,但SQL分析器会话可能能够回答这个问题。
事后编辑:当然最简单的答案可能是并发,特别是如果这是一个Web应用程序,两个请求可能同时进入并重叠。
答案 1 :(得分:0)
任务是否可以为空PlanID
(为什么它有时会起作用)?顶部的删除看起来很可疑,您是否应该将PlanID
设置为新创建的planRecord
?无论哪种方式,您都将其设置为不再存在的计划,因此级联可能无法在某处工作(例如,它应该将死计划作为Task
和Bucket
的外键取消。 / p>