强类型数据表/数据集中的可为空类型 - 解决方法?
强类型 DataTable 支持“可空”字段类型,但设计器不允许您将任何值类型字段的设置更改为“允许空”。 (即:字符串类型允许可为空,但 int 类型不允许)。
解决方法是每当您想要获取 Myfield 时调用 IsMyFieldNull()。如果您在 MyField 确实包含 null 时访问它,则会引发异常。
这是一个非常令人头痛的问题,此外,当出现 null 时会导致应用程序崩溃,从而导致许多运行时错误。我已经向微软抱怨了很多年,但 Visual Studio 的每个新版本仍然不允许使用可空值类型。
我的问题:有人知道可以用来解决这个主要缺点的奇特扩展方法吗?
Strongly-typed DataTables support "nullable" field types, except that the designer will not allow you change the setting to "allow nulls" for any value type fields. (ie: String types allow nullable, but int's do not).
The workaround is to call IsMyFieldNull() any time you want to get Myfield. If you access MyField when it does contain a null, it throws an eception.
This is a massive headache, in addition to causing many runtime bugs when a null showing up can cause your app to crash. I've complained to microsoft for years about this, yet every new release of visual studio still does not allow nullable value types to be used.
My question: Anyone know of a fancy extension method(s) that could be used to work around this major shortcoming?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(7)
如果您使用 .Net 3.5 或更高版本,这些扩展可能对您有用:
http://msdn.microsoft.com/en-us /library/system.data.datarowextensions.field.aspx
根据文档,它完全支持可空类型。它允许您使用类似的结构
,如果您将其分配给正确类型的现有变量或从正确类型的现有变量分配它,编译器可以自动推断类型,并且您可以省略类型说明符,使其尽可能短仍然
不完美,但是比到处使用 IsMyFieldNull() 等更清晰。
哦,如果您想在拼写错误的列名称方面更加安全,您可以使用诸如“
不要忘记添加对 System.Data.DataSetExtensions”的引用之类的内容。
If you are using .Net 3.5 or higher, may be these extensions might be of use to you:
http://msdn.microsoft.com/en-us/library/system.data.datarowextensions.field.aspx
According to the documentation, it fully supports nullable types. It allows you to use constructs like
and if you assign it to or from an existing variable of the correct type, the compiler can infer the type automatically and you can leave out the type specifier, making it as short as
Still not perfect, but a lot more legible than having to use IsMyFieldNull() etc everywhere.
Oh and if you want to be more on the safe side regarding misspelling column names, you can use things like
Don't forget to add a reference to System.Data.DataSetExtensions.
在 VS 2008 中,您只需在 nullvalue 属性中输入“0”即可。
如果您使用的是 vs2005,则必须使用 XML 编辑器来完成。
您必须将
msprop:nullValue="0"
作为属性添加到该列。In VS 2008 you can just enter a '0' in the nullvalue property.
If you are using vs2005 you must do it with an XML editor.
You must add
msprop:nullValue="0"
as attribute to the column.我同意允许可为空类型是一个很好的功能。
如果将列上的“NullValue”属性设置为“-1”而不是“(引发异常)”,则当列为 null 时,该属性将返回 -1,而不是引发异常。您仍然需要将列设置为允许空值。
或者,您始终可以将数据类型设置为“System.Object”,并允许 nulls=true。您无需使用“IsMyFieldNull()”方法即可访问该列的值。当列为空时,该列的值为“System.DbNull.Value”。如果您不喜欢使用“System.DbNull.Value”,则可以将“NullValue”属性设置为“(Nothing)”而不是“(抛出异常)”,然后将该对象与空引用进行比较。
I agree that it would a nice feature to allow nullable types.
If you set the "NullValue" property on the column to "-1" instead of "(Throw exception)" the property will return a -1 when the column is null instead of throwing an exception. You still have to set the column to allow nulls.
Alternatively, you can always set the datatype to "System.Object", and allow nulls=true. You can access the value of the column without having to use the "IsMyFieldNull()" method. The value of the column will be "System.DbNull.Value" when the column is null. If you don't like using "System.DbNull.Value", you can set the "NullValue" property to "(Nothing)" instead of "(Throw exception)" and then compare the object to a null reference.
你可以这样做:
如果未设置,则将AllowDbNull 设置为true;默认值保持打开状态; NullValue 保持打开状态(抛出异常)。然后,当您想要将列设置为空时,可以使用内置方法 Set_Column_Null() 从代码中。
看我的例子:
You could do this:
set AllowDbNull to true, if it is not set; DefaultValue remains on ; NullValue remains on (Throw exception). Then from code when you want to set to null a column you may use built in method Set_Column_Null().
Look my example:
我只需要为此找到一个解决方法。我需要更改一些为 ASP.NET 2.0 编写的旧网页代码。该页面使用 Telerik RadMenu,一个菜单控件。该组件要求根元素具有正确的 DBNull 值(对于parentID)。
因此,当我编译旧代码时,RadMenu 组件给我带来了很多问题。首先是关于约束的例外,然后它不知道哪些元素是根元素,整个事情看起来很糟糕。
但我解决了它,这对我有用。
在表适配器设计器的 ParentID 列的属性页面中,我使用了:
-AllowDBNull: true
- 默认值:-1(-1 是该列通常不会出现的值)
NullValue 属性仍处于“抛出异常”状态,因为对我来说不可能更改。
在使用表适配器中的值的代码中,我使用了此构造(VB.NET 代码,而不是 C#,因为此问题已标记):
为表适配器生成的代码为每列生成两个应允许 DBNULL 的函数。它们应该在处理 NULL 时使用,但这是 Microsoft 的一个笨拙的解决方案。幕后发生的事情是表适配器将从 Get 函数输出列的 DefaultValue 而不是 NULL。我称之为“模拟 NULL”或“假 NULL”。
函数 IsParentIDNull() 实际上会检查该行是否包含此“假 NULL”,例如列的 DefaultValue,当它包含时,我将使用 SetParentIDNull() 函数插入一个正确的 DBNull。
这个解决方案对我有用,但不是很优雅,也不是很有效,但我希望它对其他人有帮助。
I just had to find a work-around for this. I needed to change some old code for a web page, written for ASP.NET 2.0. The page uses Telerik RadMenu, a menu control. This component requires the root elements to have proper DBNull-values (for parentIDs).
So, when I compiled the old code, the RadMenu component gave me lots of problems. First exceptions regarding Constraints, then it did not understand which elements were root elements and the whole thing looked horrible.
But I solved it and this is what worked for me.
In the Properties page of the ParentID column in the Table Adapter designer, I used:
- AllowDBNull: true
- DefaultValue: -1 (-1 is a value that does not occur normally for that column)
THe NullValue-property stayed at "Throw Exception" as it was impossible to change for me.
And in the code using the values from the table adapter, I used this construct (VB.NET code, not C#, as this question is tagged):
The code generated for the table adapters generates two functions for each column that should allow DBNULLs. They are meant be used when dealing with NULLs, but it is a clumsy solution by Microsoft. What happens behind the scenes is that the the table adapter will output the column's DefaultValue instead of NULL from the Get-function. I call that a "simulated NULL" or a "fake NULL".
The function IsParentIDNull() will actually check if the row contains this "fake NULL", e.g. the column's DefaultValue, and when it does, I'm inserting a proper DBNull using the SetParentIDNull() function.
This solution works for me, but is not very elegant, nor is it very efficient, but it could be of help to someone else, I hope.
我不确定为什么
var x = !IsMyFieldNull() ? MyField : null
(或类似的)真是令人头痛。我想您可以在 SqlDataReader 周围编写一个包装器,以便在将数据读入 DataTable 时以某种方式捕获这些空值,或者您可以为您的查询编写相当于
.TryParse()
的内容:一些不错且封装的东西就像:其中 .TryParse 是一个扩展方法,看起来像:
正如您所看到的,这基本上是粗略的伪代码,但您明白了。编写一次代码,然后将其作为扩展方法调用。
I'm not sure why
var x = !IsMyFieldNull() ? MyField : null
(or similar) is such a headache.I suppose you could write a wrapper around SqlDataReader to trap those null values somehow when you read the data into your DataTable, or you could write the equivalent of
.TryParse()
for your queries: something nice and encapsulated like:where .TryParse is an extension method looking something like:
This is, as you can see, basically pseudo-code rough, but you get the idea. Write your code once, then call it as an extension method.
可空类型是在 .net 3.0 中引入的,它们可以与数据集一起使用。你像这样声明一个可以为 null 的 int
int? myNullableInt = null
以下是 MSDN 文章的链接:可空类型 C#< /a>
就个人而言,我首先会避免数据库中的空值(如果您有能力这样做)。 NULL 确实允许“未定义”或“未知”状态。很少出现此问题,例如包含姓氏的字符串字段通常会设置为可为空,而默认为“”将是一个更好的选择。将空值放入数据库会使事情变得不必要的困难数据库中的空值,此外,它会将 null 传播到代码中,您必须努力避免 null 引用异常。
不幸的是,互联网上有很多关于 DB 的不好的东西(比如过度使用 null 作为 OK)。这些观点通常是由真正不理解其背后理论的人提出的,另一个典型的例子是没有关系的数据库“因为在代码中处理这些更灵活/更快”。这意味着开发人员必须重写现有的[数据库层]功能,数据库不可避免地会更有效地处理这些功能,并具有更高的可靠性。我说不可避免的是,当然,进行重写的开发人员正在重新实现 Oracle/Microsoft/任何拥有大型团队花费大量时间优化等的东西。然而,时不时地,你会看到有人提倡这一点一个设计。这家伙真是懂数据库,DBDebunkings他花了很多时间试图揭穿很多废话使关系数据库脱离其理论根源的论据。
Nullable types were introduced in .net 3.0, these can be used with data sets. You declare a nullable int like this
int? myNullableInt = null
Here is a link to the MSDN article: Nullable Types C#
Personally, I'd steer clear of nulls in databases in the first place (if you have the luxry of doing this). NULL is really there to allow an "Undefined" or "Unknown" status. It is rare to have this problem, for example a String Field containing a Surname will often be set to nullable, whereas defaulting to "" would be a much better option. Putting nulls into databases makes things unnecessarily hard Null Values In Databases, additionally it propagates nulls into code and you have to work to avoid null reference exceptions.
Unfortunately there is a lot of bad stuff written on the Internet about DBs (such as the over-use of null as being OK). These viewpoints are normally by people who really don't understand the theory behind them, another classic example being a DB without relations "because it is more flexible/quicker to handle these in code". This means the dev has to re-write existing [database-layer] functionality that the database inevitability does handle more efficiently and with much greater reliability. I say inevitability as, of course, the dev doing the re-write is re-implementing stuff that Oracle/Microsoft/Whoever have had large teams spending a great deal of time optimising etc. Yet every so often, you see someone advocating this as a design. This guy really understands databases, DBDebunkings he spent a lot of time trying to debunk a lot of nonsense arugments that take relational databases away from their theoretical roots.