【问题标题】:Why does PetaPoco return from a db.Insert a ID field of 7 as a decimal为什么 PetaPoco 从 db.Insert 一个 7 作为小数的 ID 字段返回
【发布时间】:2011-06-07 21:35:58
【问题描述】:

在执行插入时,变量 id 作为对象返回。但是在我的数据库中它是一个 int 而在我的 POCO 中它是一个 int 但是当调用 ExecuteScalar 以返回 @@IDENTITY 的方法调用时,它会返回数字 7 作为一个对象,但调试器认为它是一个小数。

因此,当我执行int newID = (int)db.Insert(...) 时,它会抛出一个

InvalidCastException

这是框架错误还是 PetaPoco 错误?

【问题讨论】:

  • 看起来很奇怪。什么是 database.LastSql 在崩溃之前设置的?
  • 您的身份列是小数吗?如果是这样,也许 PetaPoco 需要将 ExecuteScalar 结果转换为 (int):stackoverflow.com/questions/2601620/…

标签: c# .net petapoco


【解决方案1】:

这将取决于您连接到的 RDBMS,您没有说明。

下面是 PetaPoco 的相关代码,它检索最后一个 id 并返回它:

object id;
switch (_dbType)
{
    case DBType.SqlServerCE:
        DoPreExecute(cmd);
        cmd.ExecuteNonQuery();
        id = ExecuteScalar<object>("SELECT @@@IDENTITY AS NewID;");
        break;
    case DBType.SqlServer:
        cmd.CommandText += ";\nSELECT SCOPE_IDENTITY() AS NewID;";
        DoPreExecute(cmd);
        id = cmd.ExecuteScalar();
        break;
    case DBType.PostgreSQL:
        if (primaryKeyName != null)
        {
            cmd.CommandText += string.Format("returning {0} as NewID", EscapeSqlIdentifier(primaryKeyName));
            DoPreExecute(cmd);
            id = cmd.ExecuteScalar();
        }
        else
        {
            id = -1;
            DoPreExecute(cmd);
            cmd.ExecuteNonQuery();
        }
        break;
    case DBType.Oracle:
        if (primaryKeyName != null)
        {
            cmd.CommandText += string.Format(" returning {0} into :newid", EscapeSqlIdentifier(primaryKeyName));
            var param = cmd.CreateParameter();
            param.ParameterName = ":newid";
            param.Value = DBNull.Value;
            param.Direction = ParameterDirection.ReturnValue;
            param.DbType = DbType.Int64;
            cmd.Parameters.Add(param);
            DoPreExecute(cmd);
            cmd.ExecuteNonQuery();
            id = param.Value;
        }
        else
        {
            id = -1;
            DoPreExecute(cmd);
            cmd.ExecuteNonQuery();
        }
        break;
    default:
        cmd.CommandText += ";\nSELECT @@IDENTITY AS NewID;";
        DoPreExecute(cmd);
        id = cmd.ExecuteScalar();
        break;
}

【讨论】:

  • 这是正确的。它确实取决于数据库。即使你做了一个 count(*) 是不同的数据库,它们都返回不同的类型,一些整数、长整数、双精度数和小数。不过,我会看看可以做些什么来使它更统一。
  • 如果您不介意修改版本的 PetaPoco 并且您的所有 PK 字段都是自动增量 ID,那么 Gareth 的答案应该对您有用。
【解决方案2】:

另外两美分。正如已经回答的那样,PetaPoco 为 SQL Server 插入返回一个小数。问题作者正在尝试强制转换为引发 InvalidCastException 的 int。但是,类型转换确实有效。所以不要这样:

int newID = (int)db.Insert(...)

这样做:

int newID = Convert.ToInt32(db.Insert(...))

【讨论】:

    【解决方案3】:

    还要记住,如果你已经设置了你的类并且你像这样插入。

    [TableName("Users")]
    [PrimaryKey("Id")]
    public class User {
        public int Id {get;set;}
        public string Name {get;set;}
    }
    
    var user = new User() { Name = "My Name" };
    db.Insert(user);
    Assert.True(user.Id != 0);
    

    user.Id 现在将从 0 更改为新创建的标识值

    【讨论】:

      【解决方案4】:

      这是一个猜测,但值得一试。在 PetePoco.cs 中尝试更改:

      id = ExecuteScalar<object>("SELECT @@@IDENTITY AS NewID;");
      

      id = ExecuteScalar<int>("SELECT @@@IDENTITY AS NewID;");
      

      【讨论】:

        猜你喜欢
        • 2019-03-08
        • 2019-01-13
        • 1970-01-01
        • 2015-01-08
        • 2014-04-22
        • 2017-03-13
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多