I'm running some C# code inside of a CLR Function and running into some strange behavior.
When the following code runs:
SqlCommand cmd = new SqlCommand();
cmd.CommandText = "SELECT * FROM Vertica_GetVerticaServer_vw WHERE verticaServe开发者_开发技巧r IS NOT NULL ORDER BY NEWID()";
using (cmd.Connection = GetSQLConnection())
{
cmd.Connection.Open();
SqlDataReader r = cmd.ExecuteReader();
while (r.Read())
{
return r.GetString(0);
}
}
This error is thrown (full relevant stack trace below):
Select statements included within a function cannot return data to a client.
However, when I run the same code, minus the "ORDER BY NEWID()" (used to randomize the result) and instead run the "ORDER BY NEWID()" inside of the view, I get no errors: Anyone know what's going on here?
SqlCommand cmd = new SqlCommand();
cmd.CommandText = "SELECT * FROM Vertica_GetVerticaServer_vw WHERE verticaServer IS NOT NULL");// ORDER BY NEWID()";
using (cmd.Connection = GetSQLConnection())
{
cmd.Connection.Open();
SqlDataReader r = cmd.ExecuteReader();
while (r.Read())
{
return r.GetString(0);
}
}
throw new Exception("Could not get Vertica Server name");
Seems like a bug, but maybe I'm missing something about the NEWID()?
(Note, I tested with GETDATE() instead to see if it was an issue with determinism, and it also worked...).
Full Stack Trace:
---> System.Data.SqlClient.SqlException: Select statements included within a function cannot return data to a client. System.Data.SqlClient.SqlException: at System.Data.SqlClient.SqlConnection.OnError(SqlException exception, Boolean breakConnection) at System.Data.SqlClient.SqlDataReaderSmi.InternalNextResult(Boolean ignoreNonFatalMessages) at System.Data.SqlClient.SqlDataReaderSmi.NextResult() at System.Data.SqlClient.SqlCommand.RunExecuteReaderSmi(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream) at System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, String method, DbAsyncResult result) at System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, String method) at System.Data.SqlClient.SqlCommand.ExecuteReader(CommandBehavior behavior, String method) at System.Data.SqlClient.SqlCommand.ExecuteReader() at Aggregation.AggregateDataManager.GetVerticaServer()
As requested, here's the setup of the CLR TVF:
[Microsoft.SqlServer.Server.SqlFunction(FillRowMethodName = "FillRowAggregates", TableDefinition = "listId int, pricingDate datetime, value decimal", DataAccess=DataAccessKind.Read)]
public static IEnumerable CalculateListAggregatePricing(int listId, DateTime start, DateTime end, int WeightTypeId)
{
DataRequest d = new DataRequest();
d.Start = start;
d.Finish = end;
d.Metric = Metric.GetSharePricingMetric();
d.Metric.Weight = WeightType.Equal;
_listId = listId;
List<ConstituentInfo> ci = new List<ConstituentInfo>();
foreach (int i in AggregateDataManager.GetConstituents(listId))
ci.Add(new ConstituentInfo(i, end));
switch (WeightTypeId)
{
case 0:
EqualWeightInterpreterForSQLCLR e = new EqualWeightInterpreterForSQLCLR();
return e.GetIndex(d, ci, false);
case 1:
MarketCapWeightInterpreterForSQLCLR mc = new MarketCapWeightInterpreterForSQLCLR();
return mc.GetIndex(d, ci, false);
case 2:
PriceWeightInterpreterForSQLCLR p = new PriceWeightInterpreterForSQLCLR();
return p.GetIndex(d, ci, false);
}
throw new Exception("Invalid Weight Type");
}
public static void FillRowAggregates(Object o, out SqlInt32 listId, out SqlDateTime pricingDate, out SqlDecimal value)
{
DataPoint dp = (DataPoint)o;
listId = _listId;
pricingDate = dp.PricingDate;
value = (SqlDecimal)dp.Value;
}
The connection is built by the WeightedInterpreters.
Have you tried something like TOP 99.99999 PERCENT?
精彩评论