【发布时间】:2015-07-06 17:47:14
【问题描述】:
数据库有一个批次数据的主表,每个批次可以有零个或多个样本。它们在 Batch.BatchID == Samples.FK_BatchID 上链接。这些表的类如下所示。
我可以向 Batches 添加一个值 - 自动增量 BatchID 会按预期更新。 我可以向 Samples 添加一个值。 我无法向 Samples 表添加多个值并获得异常
附加信息:无法使用已在使用的键添加实体。
如果我将 STOP 设置为“1”,则 db 将获得一个新批次,其中包含正确引用的新样本。我必须做什么才能允许为单个批次添加多个样品。此外,理想情况下,我希望使用相同的上下文和单个“SubmitChanges()”操作 - 但让我在跑步之前先走。
这是我尝试过的代码:
Int64 newbatchID = 0;
using (var context = new Data.BatchContext(connection))
{ // This 'chunk' work fine and the newbatchID gets the new value
context.Log = Console.Out;
Data.Batches newBatch = new Data.Batches {
Created = System.DateTime.Now.ToString("u"),
Title = "New Title",
Varietal = "Waltz"
};
// Return the Batch Id if necessary...
var qs = from c in context.sqlite_sequence
where c.name == "Batches"
select c.seq;
context.Batches.InsertOnSubmit(newBatch);
context.SubmitChanges();
newbatchID = qs.ToList().First();
}
// Use the new batch ID to submit a load of new samples
int STOP = 2; // PROBLEM. If Stop is not 1 the following fails
using (var context = new Data.BatchContext(connection))
{
context.Log = Console.Out;
List<Data.Samples> samplelist = new List<Data.Samples>();
for (var i = 0; i < STOP; ++i)
{ // Just to get different time values
System.Threading.Thread.Sleep(500);
samplelist.Add(
new Data.Samples {
// Commenting out the FK_BatchID doesn't help
FK_BatchID = newbatchID,
Created = System.DateTime.Now.ToString("u"),
ImageURI = String.Format("./Path/Img_{0}.jpg", i)
});
}
context.Samples.InsertAllOnSubmit(samplelist);
context.SubmitChanges();
}
数据库类
[Table(Name = "Batches")]
public class Batches
{
public virtual ICollection<Batches> batches { get; set; }
public Batches()
{
batches = new HashSet<Batches>();
}
// Primary key - nullable to allow Autoincrement
[Column(Name = "BatchID", IsPrimaryKey = true)]
public Int64? BatchID { get; set; }
// Batch creation date
[Column(Name = "Created")]
public String Created { get; set; }
// Other String columns the same as Created
...
}
[Table(Name = "Samples")]
public class Samples
{
public virtual ICollection<Samples> samples { get; set; }
public Samples()
{
samples = new HashSet<Samples>();
}
// Primary key - nullable to allow Autoincrement
[Column(Name = "SampleID", IsPrimaryKey = true)]
public Int64? SampleID { get; set; }
// Foreign key to the Batches Table
private EntityRef<Batches> _batch = new EntityRef<Batches>();
[Association(Name = "FK_BatchID", IsForeignKey = true,
Storage = "_batch", ThisKey = "FK_BatchID",
OtherKey = "BatchID")]
public Batches Batches
{
get { return _batch.Entity; }
set { _batch.Entity = value; }
}
// Foreign key table entry
[Column(Name = "FK_BatchID")]
public Int64? FK_BatchID { get; set; }
// Date the image was processed by the batch
[Column(Name = "Created")]
public String Created { get; set; }
// Other String columns etc
...
}
编辑:
在尝试修改列装饰(即 IsDbGenerated 和/或 DbType 等)失败后,我使用如下所示的 sqlite_sequence 实施了一项工作。这用于查找各种表 ID 的值,然后在创建新对象时使用这些值。然后这些都可以打包在一个事务中
// Start by getting the latest autoincrement values
var aiQuery = (from c in context.sqlite_sequence
select c).ToList();
Int64 batchId = 1 + aiQuery.Find(q => q.name == @"Batches").seq;
Int64 sampleId = 1 + aiQuery.Find(q => q.name == @"Samples").seq;
// Create objects etc
...
// Then update the db once only
context.Batches.InsertOnSubmit(newBatch);
context.SubmitChanges();
如果没有更好的解决方案,我会接受这个作为答案
【问题讨论】:
-
Batch没有可以添加新样本的Samples集合吗? -
@Gert:是的,使用 sqlite_sequence 的hacky 使用允许在单个事务中添加具有多个样本的新批次。