SQL Server 中的 tinyint 到 C# 中的字节
Posted
技术标签:
【中文标题】SQL Server 中的 tinyint 到 C# 中的字节【英文标题】:tinyint in SQL Server to byte in C# 【发布时间】:2014-10-13 22:31:29 【问题描述】:在数据库管理和应用程序开发中,我们必须注意空间和内存要求。我一直被教导要使用占用空间最少的数据类型来满足您的需求。
在我的场景中,我在存储值 0,1,2,3,4 (SQL Server 2012) 的表中有一个列。为此,我选择使用 tinyint 数据类型。这些值从数据库中提取到 C# 应用程序中。目前,我无法将此 tinyint 数据类型转换为字节。当我尝试时,我收到一个错误“无法将 int 隐式转换为字节”。如果我将应用程序中的数据类型更改为整数,我可以很好地提取它。与字符串相同。
出于性能目的,是否可以在我通常使用字节的整个应用程序中使用整数?如果不是,如何将整数转换为字节?
这是我使用的给出错误的代码:
string strSQL = "SELECT securityLevel FROM security WHERE employeeID=@empID;";
using (SqlConnection dbConn = new SqlConnection(connParam))
dbConn.Open();
byte level = 0;
using (SqlCommand dbCommand = new SqlCommand(strSQL, dbConn))
dbCommand.CommandType = System.Data.CommandType.Text;
dbCommand.Parameters.AddWithValue("@empID", "12345");
using (SqlDataReader dbReader = dbCommand.ExecuteReader())
while (dbReader.Read())
level = dbReader.GetByte(0);
Console.WriteLine(level);
Console.ReadLine();
我也试过了:
level = (byte)dbReader.GetValue(0);
【问题讨论】:
在GetVaue(0)
上设置断点,在VS的即时窗口中查询返回值,它会告诉你类型是什么。 (即dbReader.GetValue(0).GetType()
)
你确定securityLevel
是tinyInt
吗?从你得到的错误来看,它听起来像是int
。你如何检查它是tinyInt
,你也能显示你的连接字符串吗?如果您使用AttachDBFilename
,您正在对其进行架构更改的数据库可能不是您在程序中使用的数据库。
查找 INFORMATION_SCHEMA 并验证列类型
【参考方案1】:
是的,如果您只存储 0 - 4,您选择 TINYINT
作为数据类型是正确的。
是的,TINYINT
等同于 .Net 中的 byte
。您可以在此处查看映射列表:
http://msdn.microsoft.com/en-us/library/cc716729(v=vs.110).aspx
不,您在创建表时实际上并没有使用TINYINT
,否则您不会收到此错误。错误消息非常具体地说明源数据类型为 INT
。
不,不要使用INT
来存储这些值。这是不必要的,您尝试做的事情(即TINYINT
和byte
)是完全有效的,我已经做过很多次了。
假设您在该表中没有数百万行数据并且不断对其进行命中,请运行以下命令:
ALTER TABLE [security] ALTER COLUMN [securityLevel] TINYINT NOT NULL;
(我假设该列当前为NOT NULL
,在这种情况下,如果您在ALTER TABLE
语句中省略NOT NULL
,它将将该字段更改为TINYINT NULL
。如果该字段不是' t 目前NOT NULL
,然后就不用这部分了)
【讨论】:
谢谢。我会试试这个。由于我只使用 0 - 4 值,char(1) 不会使用更少的空间吗?如果是这样,我为什么不使用它? @nehi_d :CHAR(1)
= 1 个字节,TINYINT
= 1 个字节。占用的物理空间没有区别。但很可能 TINYINT 在 JOIN 和 WHERE 子句中表现更好。如果您在创建列(或使用该定义更改它)时使用二进制排序规则(例如 SQL_General_BIN
或 Latin1_General_BIN
),则 CHAR(1) 可能 也可能会这样做,但它似乎真的是一个数字,所以最好保持这种状态。这也让ORDER BY [SecurityLevel]
或WHERE [SecurityLevel] > 3
(或类似的东西)变得更好。
@nehi_d :你能测试一下吗?成功了吗?【参考方案2】:
我编写了以下 LinqPad(针对 SqlServer express)来验证您是否可以使用 .NET 和 SqlServer 将 tinyint 作为字节读取:
var cb = new SqlConnectionStringBuilder DataSource = @".\Sqlexpress", InitialCatalog = "Medallion_OData_Tests_CustomersContext251990930203", IntegratedSecurity = true ;
using (var c = new SqlConnection(cb.ConnectionString))
c.Open();
var cmd = c.CreateCommand();
cmd.CommandText = "SELECT CAST(1 AS tinyint)";
var reader = cmd.ExecuteReader();
reader.Read();
reader.GetByte(0).Dump();
这表明您的数据库中实际的 securityLevel 列不是 TINYINT 类型。为了验证,为什么不临时修改您的选择查询以包含一个 CAST 到 TINYINT,就像我的示例中一样?如果这可行,那将确认表架构是问题所在。
检查实际表架构的其他方法包括查询 sys.columns 或在 SqlServer Management Studio 中突出显示表的名称并按 ALT+F1。
【讨论】:
【参考方案3】:我认为最安全的方法是使用Convert.ToByte Method:
level = Convert.ToByte(dbReader.GetValue(0));
它从许多值类型转换为字节。
【讨论】:
以上是关于SQL Server 中的 tinyint 到 C# 中的字节的主要内容,如果未能解决你的问题,请参考以下文章
sql server intbigintsmallint 和 tinyint
将 SQL Server tinyint 映射到 Int16 的实体框架
使用 TinyInt 还是 Bit 对 SQL Server 有影响吗?大小和查询性能