C# GUID与SQL Server Uniqueidentifier转换及Google Chart数据查询问题
解决Google Chart中使用UniqueIdentifier参数查询SQL Server数据的问题
首先要明确一个关键误区:UniqueIdentifier(GUID)不能直接转换为int。GUID是128位的全局唯一标识符,而int只是32位整数,两者的取值范围、存储结构完全不同,强行转换要么会抛出溢出异常,要么会丢失大量信息,完全无法正确匹配数据库中的UserID。正确的做法是直接在存储过程和C#代码中使用uniqueidentifier类型来传递参数,下面是具体的实现步骤:
1. 调整存储过程,启用UserID参数
修改你的存储过程,打开注释的@UserID参数,并调整WHERE子句来支持按UserID过滤(如果需要同时保留ActivityID过滤,可以做成可选参数的形式,让查询更灵活):
SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO ALTER PROCEDURE [dbo].[rpGetUserActivities] ( @UserID uniqueidentifier, -- 启用UniqueIdentifier类型的参数 @ActivityID INT = NULL -- 设置为可选参数,按需使用 ) AS BEGIN SELECT [UserID], [ActivityID], [Title], [DateCreated] FROM [DB].[dbo].[DB_Activity] WHERE [DateCreated] IS NOT NULL -- 支持单参数或多参数组合过滤 AND (@ActivityID IS NULL OR [ActivityID] = @ActivityID) AND (@UserID IS NULL OR [UserID] = @UserID) END
2. 修改C#中的数据访问方法,适配UniqueIdentifier参数
更新你的rpGetUserActivities方法,将参数类型改为Guid?(对应SQL的uniqueidentifier),并正确添加存储过程参数:
/// <summary> /// 根据UserID(可选结合ActivityID)获取用户活动记录 /// </summary> /// <param name="UserID">用户唯一标识符</param> /// <param name="ActivityID">活动ID(可选)</param> /// <returns>用户活动记录列表</returns> public List<rpusersRecord> rpGetUserActivities(Guid? UserID, Int16? ActivityID = null) { List<rpusersRecord> objrpusersRecords = null; objDB = new SqlDatabase(ConnectionString); using (DbCommand objcmd = objDB.GetStoredProcCommand("rpGetUserActivities")) { // 处理UserID参数:如果有值则传入,否则传DBNull if(UserID.HasValue) { objDB.AddInParameter(objcmd, "@UserID", SqlDbType.UniqueIdentifier, UserID.Value); } else { objDB.AddInParameter(objcmd, "@UserID", SqlDbType.UniqueIdentifier, DBNull.Value); } // 保留ActivityID参数的处理逻辑(如果需要) if(ActivityID.HasValue) { objDB.AddInParameter(objcmd, "@ActivityID", DbType.Int16, ActivityID.Value); } else { objDB.AddInParameter(objcmd, "@ActivityID", DbType.Int16, DBNull.Value); } try { using (DataTable dataTable = objDB.ExecuteDataSet(objcmd).Tables[0]) { objrpusersRecords = ConvertTo<rpusersRecord>(dataTable); } } catch (Exception ex) { throw ex; return null; } } return objrpusersRecords; }
3. 确保实体类的属性类型匹配
你的ConvertTo<T>方法依赖反射赋值,所以要保证rpusersRecord类中的UserID属性类型是Guid(或Guid?如果数据库中允许UserID为空):
public class rpusersRecord { public Guid UserID { get; set; } public int ActivityID { get; set; } public string Title { get; set; } public DateTime DateCreated { get; set; } // 其他对应数据表的属性 }
为什么不能把UniqueIdentifier转成Int?
再强调一下这个错误思路的问题:
- GUID的数值范围远超过int的上限(int最大是2147483647),强行转换会直接抛出
OverflowException。 - 即使通过截断等方式强行转换,也会丢失GUID的大部分唯一标识信息,导致无法正确匹配数据库中的用户ID,完全违背了GUID作为唯一标识符的设计初衷。
内容的提问来源于stack exchange,提问作者zufuzoje
相关产品推荐
相关产品推荐

