Qaz*_*zzi 2 vb.net sqlite datagridview
我有一个带有名为tbl_invent的表的sqlite DB,在窗体加载时,它用表中的内容填充了datagridview。问题是我有字段名称cost和sell_price,字段名称都有小数点,并且在加载表单时它仅显示数字而不是小数。
样品:
表格= 1.75,DGV = 1.00
Private Sub Form1_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
connect()
Dim da As New SQLiteDataAdapter("select * from tbl_Invent", connection)
Dim ds As New DataSet
da.Fill(ds, "tbl_Invent")
DataGridView1.DataSource = ds
DataGridView1.DataMember = "tbl_Invent"
DataGridView1.Columns(6).ValueType = GetType(Single)
DataGridView1.Columns(6).DefaultCellStyle.Format = "N2"
DataGridView1.Columns(7).ValueType = GetType(Single)
DataGridView1.Columns(7).DefaultCellStyle.Format = "N2"
connection.Close()
da.Dispose()
End Sub
Run Code Online (Sandbox Code Playgroud)
我已经检查了正确的字段类型“整数”,我也尝试了“ GetType(Single)”和“ GetType(Decimal)”,但仍然相同。谁能指出我正确的方向?谢谢。
来自评论:
SQLite中没有其他类型。在SQLite中也只有“文本”,“整数”,“实数”和“斑点”,它表示整数可以有小数。
您没有指明正在使用的数据库提供程序,但是标准提供程序(来自SQLite开发人员)将看到Integer数据并将其映射到Int32不允许小数的NET 类型。 Real将节省分数Decimal。
there is no other type in SQLite. there is only "Text", "Integer", "Real" and "Blob"
是的,但这适用于SQLite数据库,而不适用于数据库提供程序。标准的DB Provider巧妙地编写为能够将4种基本类型转换为各种NET类型,从而使实际的存储类型/格式成为实现细节。
提供者代码包括执行转换的许多步骤,查找表,子系统,词典和方法。甚至还有一种定义自定义类型名称的方法。以下是工作原理的一般说明。
字节,SByte
INT8,INTEGER8,TINYSINT(SByte)UINT8,UNSIGNEDINTEGER8,TINYINT(字节)
整数(短,长,有符号,无符号等)
BIGINT,BIGUINT,COUNTER,IDENTITY,INT,INT16,INT32,INT64,INTEGER,INTEGER16,INTEGER32,INTEGER64,LONG,SMALLINT,SMALLUINT,UINT,UINT16,UINT32,UINT64,ULONG ,UNSIGNEDINTEGER,UNSIGNEDINTEGER16,UNSIGNEDINTEGER32,UNSIGNEDINTEGER64
布尔
BIT,BOOL,BOOLEAN,LOGICAL,YESNO
文字/字串
CHAR,CLOB,LONGCHAR,LONGTEXT,LONGVARCHAR,MEMO,NCHAR,NOTE,NTEXT,NVARCHAR,STRING,TEXT,VARCHAR,VARCHAR2
数值
DOUBLE,FLOAT,REAL;单(单)
十进制
货币,十进制,货币,数字,数字
BLOB
BINARY,BLOB,GENERAL,IMAGE,OLEOBJECT,RAW,VARBINARY
日期/时间
DATE,DATETIME,SMALLDATE,TIME,TIMESTAMP
GUID
GUID,唯一身份
来源:SQLiteDbTypeMap中SQLiteConvert.cs(1.0.103版; 9月,2016)。
本质上,DBProvider 以适当的SQLite类型存储数据,但是在回读它时,它将使用在表定义中使用的类型将数据转换回NET类型。SQLite提供程序包括一个大型SQLiteConvert类,可以为您完成所有转换。
尽管对于SQLite奉献者来说这似乎是常识,但我找不到狂野的记载。大多数站点只是重新格式化SQLite网站内容。它可能记录在帮助文件中,但是我的主题中没有内容。根据列表,很容易意外使用有效名称并发现其有效。
该列表合并了其他DB使用的最常见的符号,以及一些NET类型。例如,Boolean可以定义为BIT, BOOL, BOOLEAN, LOGICAL or YESNO。因此,此表定义是合法的并且具有完整功能:
CREATE TABLE LiteColTypes (
Id INTEGER PRIMARY KEY AUTOINCREMENT,
Name TEXT,
ItemDate DATETIME,
Char3 CHAR (3),
UINT32 UINT32,
Value INT16,
VarChar5 VARCHAR (5),
GCode GUID,
Price DECIMAL,
ItemImg IMAGE,
Active BOOL,
NotActive YESNO
);
Run Code Online (Sandbox Code Playgroud)
有几件事要注意,还有一些有用的DateTime选项。
该列表来自以下代码:
CREATE TABLE LiteColTypes (
Id INTEGER PRIMARY KEY AUTOINCREMENT,
Name TEXT,
ItemDate DATETIME,
Char3 CHAR (3),
UINT32 UINT32,
Value INT16,
VarChar5 VARCHAR (5),
GCode GUID,
Price DECIMAL,
ItemImg IMAGE,
Active BOOL,
NotActive YESNO
);
Run Code Online (Sandbox Code Playgroud)
XML注释被保留,因为它具有启发性和权威性:
构建并返回包含此提供程序识别的数据库列类型的映射。(强调我的)。
这DbType对过程至关重要。
上面的代码SQLiteDbTypeMap将它识别出的许多许多列名称与一个DbType用于确定要返回的NET数据类型相关联。该列表足够全面,可以为您转换除1或2种类型之外的所有类型。
例如,请注意,GUID和IMAG*都存储为BLOB,但GUID类型名称与不同的相关联DbType,其允许该被比不同地返回BLOB IMAGEBLOB。
您也可以通过连接对象指定类型。空格和作用域不允许解释,但是虽然有点乏味,但它允许您为自定义类型名称提供数据类型。
存储数据时,您无需担心如何存储数据。DB Provider将使用DbType传递来查找要使用的SQLite类型(Affinity“。如果使用AddWithValue或(过时的)Add(object, object)重载,则DBProvider会猜测类型。在猜测上相当不错,但不要这么做。
因此,不需要此转换:
/// <summary>
/// Builds and returns a map containing the database column types
/// recognized by this provider.
/// </summary>
/// <returns>
/// A map containing the database column types recognized by this
/// provider.
/// </returns>
private static SQLiteDbTypeMap GetSQLiteDbTypeMap()
{
return new SQLiteDbTypeMap(new SQLiteDbTypeMapping[] {
new SQLiteDbTypeMapping("BIGINT", DbType.Int64, false),
new SQLiteDbTypeMapping("BINARY", DbType.Binary, false),
new SQLiteDbTypeMapping("BIT", DbType.Boolean, true),
new SQLiteDbTypeMapping("BLOB", DbType.Binary, true),
new SQLiteDbTypeMapping("BOOL", DbType.Boolean, false),
new SQLiteDbTypeMapping("BOOLEAN", DbType.Boolean, false),
...
new SQLiteDbTypeMapping("GUID", DbType.Guid, false),
new SQLiteDbTypeMapping("IMAGE", DbType.Binary, false)
... (many more)
Run Code Online (Sandbox Code Playgroud)
使用与任何其他数据库相同的代码:
cmd.Parameters.Add("@g", DbType.Binary).Value = myGuid.ToByteArray();
Run Code Online (Sandbox Code Playgroud)
笔记:
DbType来描述传递的数据,而不是您认为应如何保存(例如DbType.Guid,而不是Binary用于Guid)。提供者将执行大多数转化。DbType.Image这样一个字节数组转换是必要的。Char()/VarChar()字段指定大小不会限制保存的字符数。这似乎是一个错误,因为保存的字符数超过定义的字符数可能会阻止加载该行。UInt16相反的方法:尝试传递超出范围的值,例如UInt16的-5,将导致Overflow Exception。但是它将65531为已存储的该值返回。Decimal(9,2)列)似乎无关紧要。内部表提供固定的精度和大小。DbType.DateTime。永远都不需要传递特定格式的字符串。提供者知道事情。(请参阅下面的DateTime选项。).Value = DateTime.Now.Date。 两个不同的查询表用于保存和读取数据,它们的共同点是DbType这就是为什么它很重要。使用正确的数据可确保数据可以往返。避免使用AddWithValue。
加载数据不需要任何特殊操作:
' // add trailing semicolons for c#
cmd.Parameters.Add("@n", DbType.String).Value = "Ziggy"
cmd.Parameters.Add("@dt", DbType.DateTime).Value = DateTime.Now
cmd.Parameters.Add("@c3", DbType.StringFixedLength, 3).Value = "XYZ123" '// see notes
cmd.Parameters.Add("@u", DbType.UInt16).Value = 3
cmd.Parameters.Add("@g", DbType.Guid).Value = myGuid
cmd.Parameters.Add("@p", DbType.Decimal).Value = 3.14D
'// 'ToByteArray()' is an extension method to convert
cmd.Parameters.Add("@img", DbType.Binary).Value = myImg.ToByteArray()
cmd.Parameters.Add("@act", DbType.Boolean).Value = True
Run Code Online (Sandbox Code Playgroud)
DGV可以正确识别并显示GUID,图像和布尔值列。每个的数据类型DataColumn都符合预期:
Run Code Online (Sandbox Code Playgroud)Name ---> System.String (maxLen = 2147483647) ItemDate ---> System.DateTime Char3 ---> System.String (maxLen = 3) UINT16 ---> System.UInt16 VarChar5 ---> System.String (maxLen = 5) GCode ---> System.Guid Price ---> System.Decimal ItemImg ---> System.Byte[] Active ---> System.Boolean NotActive ---> System.Boolean
请注意,Guid和Image项都存储为,BLOB但返回的方式不同。Active(BOOL)和NotActive(YESNO)使用不同的类型名称,但返回相同的数据类型。一切都按需工作。
TIME作为列类型名称不能按预期工作。它不会解析DateTime.Now.TimeofDay(Timespan)。该表将TIME映射到DbType.DateTime。
请勿使用 DbType.DateTime2或.DateTimeOffset。这些在转换器查找中丢失,因此数据以无效格式(版本1.0.103.0)存储为文本。
SQLite NET提供程序不只支持一种日期格式。当另存为UTC时,数据包括一个指示器。但是,无论是保存为本地或UTC时,Kind总是返回的Unspecified。解决此问题的方法之一是添加datetimekind到您的连接字符串中:
`...;datetimekind=Utc;`
`...;datetimekind=Local;`
Run Code Online (Sandbox Code Playgroud)
这将设置Kind为所有DateTime的值返回,但没有转化价值。
为补救这是使用(相对)新的BindDateTimeWithKind连接标志。这将转换日期,以配合DateTimeKind在连接的保存:
// Dim SQL = "SELECT * FROM LiteColTypes" ' for VB
string SQL = "SELECT * FROM LiteColTypes";
...
dbCon.Open();
Dim dt As New DataTable();
dt.Load(cmd.ExecuteReader());
dgv.DataSource = dt;
Run Code Online (Sandbox Code Playgroud)
尽管已传递本地日期,但BindDateTimeWithKind结果会保存为UTC以匹配连接。由于“ DateTimeKind = Utc;”而返回UTC日期。连接设置。
请注意,在保存日期时起作用,而DateTimeKind在读取日期时BindDateTimeWithKind起作用。个别而言,它们似乎会使情况变得更糟。整个数据库一起成为基于UTC(或本地)的日期,日期统一保存并读取为同一日期-您无需执行任何操作。 Kind
ConnectionFlags 在连接字符串中指定它们会很麻烦,因为它们需要手动操作:
connx = "...;datetimekind=Utc;flags='Default, BindDateTimeWithKind';"
Run Code Online (Sandbox Code Playgroud)
限制/问题
均匀Kind处理对a DbDataReader和至少与Dapper一起有效。但是,使用时DataTable,Kindfor日期仍未指定。显然,这是由于Microsoft 的DateTimeMode特性,DataColumn并且可能是Microsoft的一项设计决定,即不假定列中的所有日期都将始终相同Kind。这也体现在其他数据库中。
使用UTC或本地连接时,提供程序将不指定未指定(这同样适用于查询中的日期)。因此,不应有任何不希望的额外转换:读取的UTC日期和“伪装为”未指定的UTC日期DataTable不会在更新中再次转换。
与“传统智慧”日期相反,日期并不总是且仅保存为TEXT。为了节省一点空间,您可以保存刻度值。由于这些不能具有时区指示符,因此Kind相关选项可能非常有用。要启用Ticks,请使用DateTimeFormat连接字符串选项:
Private LiteConnStr = "...;datetimekind=Utc;DateTimeFormat=Ticks;..."
'e.g: 634939900800000000
Run Code Online (Sandbox Code Playgroud)
其他DateTimeFormat选项包括CurrentCulture,ISO8601(默认设置),JulianDay和UnixEpoch。无需更改列类型名称即可使用这些格式之一。现在仍然是日期,SQLite Provider将根据连接标志处理实现细节。
UI浏览器
许多SQLite UI浏览器似乎只知道四种规范类型。也许这是故意的,但这限制了它们对NET开发人员的实用性,并隐藏了NET提供程序的功能。
SQLiteStudio(版本:3.1.0)提供了更多功能,但它似乎并不了解完整列表,因为缺少了一些非常有用的功能(例如GUID,IMAGE,SINGLE,整数变体)。
它确实允许您输入所需的任何类型名称,因此,Profit!
DBType确定实际的返回数据类型DbType保存数据时使用正确的数据可确保数据往返DateTimeKind和BindDateTimeWithKind选项允许日期的自动,统一存储时区首先,NET提供程序使实际存储成为实现细节。