OrmLite中的错误 - 使用主键更新记录= 0

时间:2016-08-31 21:10:58

标签: servicestack ormlite-servicestack

给出一个简单的poco

public class Model
{
    [PrimaryKey]
    public int ID { get; set; }
    public string Description { get; set; }
} 

这很好......

var connectionString = @"Data Source=WIN8PC\SQLEXPRESS;Initial Catalog=Test;Integrated Security=True;";
connectionFactory = new OrmLiteConnectionFactory(connectionString, SqlServerDialect.Provider);

using (var db = connectionFactory.OpenDbConnection())
{ db.DropAndCreateTable<Model>(); }

var model0 = new Model { ID = 0, Description = "Item Zero" };
var model1 = new Model { ID = 1, Description = "Item One" };

using (var db = connectionFactory.OpenDbConnection())
{ db.Save(model0, model1); }

就像这样...

model0.Description += " updated";
model1.Description += " updated";

using (var db = connectionFactory.OpenDbConnection())
{ 
    db.Save(model0); 
    db.Save(model1);
}

但是,这会因主键违规异常而崩溃...

model0.Description += " updated again";
model1.Description += " updated again";

using (var db = connectionFactory.OpenDbConnection())
{ db.Save(model0, model1); }

需要ID为零的记录,因为这是一个替换现有C#枚举类型的查找表。这是分布式数据的本地副本(我无法控制),因此没有理由拥有自动增量密钥。

问题似乎在OrmLiteWriteCommandExtensions.SaveAll()中 - 任何具有id == defaultValue的行都被假定为新项目,而不是现有记录的更新。同样的问题也出现在并行异步方法中。

除了单独保存每条记录(在交易中)之外,还有其他方法可以解决此问题。最好在一个命令中保存表的所有更新记录。

1 个答案:

答案 0 :(得分:1)

Save是一个高级API,它将根据主键是否具有值来INSERT或UPDATE。如果要插入默认主键值,可以使用Insert,如此Live Example on Gistlyn中所示:

public class Model
{
    [PrimaryKey]
    public int ID { get; set; }
    public string Description { get; set; }
} 

db.DropAndCreateTable<Model>();

var model0 = new Model { ID = 0, Description = "Item Zero" };
var model1 = new Model { ID = 1, Description = "Item One" };

db.Insert(model0, model1);

var rows = db.Select<Model>();

"Inserted Rows: {0}".Print(rows.Dump());

哪个输出:

Inserted Rows: [
    {
        ID: 0,
        Description: Item Zero
    },
    {
        ID: 1,
        Description: Item One
    }
]