我正在尝试使用Peta POCO ORM而我非常喜欢它,但有一件事我无法工作。我使用MS SQL和带uniqueidentifier的表作为主键。但是,当我插入新记录时,POCO会抛出一个InvalidCastException,试图将DBNull强制转换为Guid。我创造了一个简单的例子。 MS SQL表定义:
CREATE TABLE MyTable
(
id uniqueidentifier NOT NULL DEFAULT newid(),
name nvarchar(50) NULL,
surname nvarchar(50) NULL,
CONSTRAINT pk_MyTable PRIMARY KEY (id)
)
然后在C#中我有:
[PetaPoco.TableName("MyTable")]
[PetaPoco.PrimaryKey("id")]
public class MyTable
{
public Guid id { get; set; }
public string name { get; set; }
public string surname { get; set; }
}
最后我尝试插入新记录:
using (var conn = new SqlConnection(myConnString))
{
conn.Open()
using (var db = new PetaPoco.Database(conn))
{
for (int i = 0; i < 3; i++)
{
var table = new MyTable() { name = "oh my", surname = i.ToString() };
db.Insert(table);
}
}
}
感谢您的帮助
答案 0 :(得分:5)
我遇到了同样的问题,试图插入带有Guid PK的表格。不幸的是,单独的明确答案还不足以解决我的问题。
我的解决方案是如上所述,使用Guid.NewGuid()手动设置Id,但也使用以下语法进行插入。重要的是自动增量。
db.Insert("MyTable", "id", false, table);
这些参数映射到: table_name,pk_column_name,use_auto_increment,object
答案 1 :(得分:2)
我相信你需要在调用Insert之前预先填充guid类型的主键。 PetaPoco(至少在V4中)支持插入后自动填充标识列。对于guid列,您需要通过调用Guid.NewGuid自己生成guid。
这不是PetaPoco&#34;限制&#34;。 SQL Server将最后生成的标识值保留在内存中,可以使用SCOPE_IDENTITY(),@@ IDENTITY或CHECK_IDENT(取决于您需要的范围)在INSERT之后立即检索。没有类似的东西捕获最后生成的GUID值。如果您使用GUID,则必须创建自己的机制来捕获最后插入的值(即在插入之前检索GUID。
答案 2 :(得分:1)
这也是我的问题,但我无法在任何地方找到答案。所以,我为自己找到了它。实际上,这是petapoco的限制,因为它不会检查Guid键的自动增量。
让我们在文件PetaPoco.Core.ttinclude中找到以下一行:
col.IsAutoIncrement=((int)rdr["IsIdentity"])==1 //This is only check for integer key.
修复:
col.IsAutoIncrement=((int)rdr["IsIdentity"])==1 ||
(!DBNull.Value.Equals(rdr["DefaultSetting"]) && ((string)rdr["DefaultSetting"] == "(newsequentialid())" ||
(string)rdr["DefaultSetting"] == "(newid())"));
&#34; DefaultSetting&#34;是您在数据库中为列设置的默认值。对于Guid,它可能是newsequentialid()或newid(),它取决于你。