【发布时间】:2019-01-17 13:06:01
【问题描述】:
我正在尝试编写一个允许我在 SQL Server 上运行 WMI 查询的 CLR。
using System;
using System.Data.Sql;
using Microsoft.SqlServer.Server;
using System.Collections;
using System.Data.SqlTypes;
using System.Diagnostics;
using System.Management;
public class WMIQuery
{
[SqlFunction(FillRowMethodName = "FillRow")]
public static IEnumerable InitMethod()
{
ManagementScope scope = new ManagementScope();
scope = new ManagementScope(@"\\localhost\root\CIMV2");
scope.Connect();
SelectQuery query = new SelectQuery("SELECT Name, Capacity, Freespace FROM Win32_Volume WHERE DriveType=3");
ManagementObjectSearcher searcher = new ManagementObjectSearcher(scope, query);
ManagementObjectCollection retObjectCollection = searcher.Get ( );
return retObjectCollection;
}
public static void FillRow(Object obj, out SqlString Name, out SqlInt64 Capacity, out SqlInt64 Freespace)
{
ManagementObject m = (ManagementObject)obj;
Name = new SqlString((string)m["name"]);
Capacity = new SqlInt64((Int64)m["Capacity"]);
Freespace = new SqlInt64((Int64)m["Freespace"]);
}
}
运行该表值函数时,出现以下错误:
从用户定义的值表中获取新行时出错 功能:System.InvalidCastException:指定的强制转换无效。 System.InvalidCastException:在 WMIQuery.FillRow(对象 obj, SqlString& 名称、SqlInt64& 容量、SqlInt64& 可用空间)。
我已经发现问题出在转换上:
Capacity = new SqlInt64((Int64)m["Capacity"]);
Freespace = new SqlInt64((Int64)m["Freespace"]);
我希望有人知道如何解决上述问题?
我测试这个 CLR 的代码是:
CREATE FUNCTION [dbo].[WMIQuery]()
RETURNS TABLE (
[Name] [nvarchar](4000) NULL,
[Capacity] [bigint] NULL,
[Freespace] [bigint] NULL
) WITH EXECUTE AS CALLER
AS
EXTERNAL NAME [MyFirstAssembly].[WMIQuery].[InitMethod]
GO
select * from WMIQuery()
【问题讨论】:
-
您的行值之一是
NULL?以防万一,您可能需要改用Nullable<Int64>。如果其中一个值是NULL,则转换为SqlInt64将失败,因为它需要一个有效的Int64。如果您可以从数据库表中提供一些示例数据,那将会很有帮助。 -
请发布您的数据库表的架构并提供一些示例数据。
-
不要使用 SQLCLR,而是使用 sys.dm_os_volume_stats 视图
-
我添加了代码来测试 CLR @RyanWilson。
-
@PanagiotisKanavos 我正在使用 win32_volume 类作为我想到的未来 wmi 查询的示例。无论如何,谢谢你把我带到 dmv。
标签: c# sql-server wmi sqldatatypes sqlclr