Petapoco在vb.net中具有可空的SQl Server smallint和int16的问题

Petapoco issue with nullable SQl Server smallint and int16 in vb.net

我有一个带有视图和小字段的SQL Server表。视图中的所有数据都自动从petapoco t4 generator标记为可以为空,因为您不能在视图中指定它。到目前为止,我对所有其他数据类型(guid、int、tinyint、string等)都没意见,但是可以为空的smallint似乎会导致一些问题。

vb.net中的t4生成器为smallint字段创建此项:

1
2
3
4
5
6
7
8
9
10
    Private mPasswordResetDays As Integer?
    <Column> _
    Public Property PasswordResetDays() As Integer?
        Get
            Return mPasswordResetDays
        End Get
        Set
            mPasswordResetDays = Value
        End Set
    End Property

但我收到一个例外:

从'system.int16'强制转换为'system.nullable'1[[system.int32,mscorlib,version=4.0.0.0,culture=neutral,publicKeyToken=b7a5c561934e089]]'

在Petapoco 2677号线:

1
2
3
4
5
Line 2675:       else
Line 2676:       {
Line 2677:          converter = src => Convert.ChangeType(src, dstType, null);
Line 2678:       }
Line 2679:            }

从petapoco执行的SQL命令非常简单:

1
2
3
4
SQL Command: SELECT UserId, AllowPersistentCookie, MinPasswordLenght,
NonAlphanumericPasswordChars, AlphanumericPassword, PasswordResetDays FROM
EVA_vw_UserLoginStatusFromRoles
WHERE UserId = @0 -> @0 [String] ="d85674ab-d389-4548-ad89-5322892ca0e2"

我认为在返回空值的executescalar命令中也发现了类似的问题,但是行和代码也不同。

如果我将类型从integer改为integer?对于整数,使它们不可以为空,一切都可以正常工作。

关于Petapoco和SQL Server smallints的这个问题有什么提示吗?

附录:视图代码为:

1
2
3
4
5
6
7
8
9
10
SELECT     a.UserId, CAST(MIN(CAST(b.AllowPersistentCookie AS int)) AS bit) AS AllowPersistentCookie, MAX(b.MinPasswordLenght) AS MinPasswordLenght,
                  CAST(MAX(CAST(b.NonAlphanumericPasswordChars AS int)) AS bit) AS NonAlphanumericPasswordChars, CAST(MAX(CAST(b.AlphanumericPassword AS int)) AS bit)
                  AS AlphanumericPassword, MIN(b.PasswordResetDays) AS PasswordResetDays
FROM         dbo.EVA_UsersInRoles AS a INNER JOIN
                  dbo.EVA_Roles AS b ON a.RoleId = b.RoleId
WHERE       (DATEDIFF(day, CONVERT(date, GETUTCDATE()), a.StartDate) <= 0) AND (DATEDIFF(day, CONVERT(date, GETUTCDATE()), a.EndDate) >= 0) OR
                  (DATEDIFF(day, CONVERT(date, GETUTCDATE()), a.StartDate) <= 0) AND (a.EndDate IS NULL) OR
                  (DATEDIFF(day, CONVERT(date, GETUTCDATE()), a.EndDate) >= 0) AND (a.StartDate IS NULL) OR
                  (a.EndDate IS NULL) AND (a.StartDate IS NULL)
GROUP BY a.UserId


此问题及解决方案位于https://github.com/toptensoftware/petapoco/issues/153

Petapoco需要修补:

1
2
3
- converter = delegate(object src) { return Convert.ChangeType(src, dstType, null); };
+ var underlyingType = Nullable.GetUnderlyingType(dstType) ?? dstType;
+ converter = src => Convert.ChangeType(src, underlyingType, null);

视图是一个红鲱鱼;您可以通过返回一个int NULL列作为uint?或类似的列,在具体的表上复制它。


它使用表生成代码,但现在从视图中获取值。SQL必须在视图中将该列提示为不可为空。