Must declare the scalar variable "#historyId" exception - sqlcommand

I have a working raw Sql command execution
using (var cmd = SqlUtils.CreateSqlCommand(cmdText, sqlConn))
{
cmd.Parameters.Add(new SqlParameter("historyId", SqlDbType.Int)).Value = AAverage.CashFlowRelevantHistoryId;
cmd.Parameters.Add(new SqlParameter("nodeId", SqlDbType.Int)).Value = AAverage.CashNodeId;
cmd.Parameters.Add(new SqlParameter("denomId", SqlDbType.Int)).Value = AAverage.DenominationId;
cmd.Parameters.Add(new SqlParameter("dayId", SqlDbType.Int)).Value = AAverage.CashFlowDayCategoryId;
cmd.Parameters.Add(new SqlParameter("hour", SqlDbType.Int)).Value = AAverage.Hour;
cmd.Parameters.Add(new SqlParameter("type", SqlDbType.Int)).Value = AAverage.ValueType;
cmd.Parameters.Add(new SqlParameter("average", SqlDbType.Real)).Value = AAverage.AverageDerivative;
using (var reader = cmd.ExecuteReader())
if (reader.HasRows && reader.Read())
{
IDataRecord record = (IDataRecord)reader;
AAverage.Id = record.GetInt32ByName("Id");
}
}
but if I've changed it to use SqlQuery method, I get the error in the subject:
StringBuilder cmdText = new StringBuilder();
cmdText.AppendLine("INSERT INTO CashFlowAverageDerivatives");
cmdText.AppendLine(" (CashFlowRelevantHistoryId, CashNodeId, DenominationId, CashFlowDayCategoryId, Hour, ValueType, AverageDerivative)");
cmdText.AppendLine("VALUES");
cmdText.AppendLine(" (#historyId, #nodeId, #denomId, #dayId, #hour, #type, #average)");
cmdText.AppendLine("SELECT Id FROM CashFlowAverageDerivatives WHERE ##ROWCOUNT > 0 and Id = scope_identity()");
AAverage.Id = ADbContext.Database.SqlQuery<int>(
cmdText.ToString(),
new SqlParameter("historyId", SqlDbType.Int).Value = AAverage.CashFlowRelevantHistoryId,
new SqlParameter("nodeId", SqlDbType.Int).Value = AAverage.CashNodeId,
new SqlParameter("denomId", SqlDbType.Int).Value = AAverage.DenominationId,
new SqlParameter("dayId", SqlDbType.Int).Value = AAverage.CashFlowDayCategoryId,
new SqlParameter("hour", SqlDbType.Int).Value = AAverage.Hour,
new SqlParameter("type", SqlDbType.Int).Value = AAverage.ValueType,
new SqlParameter("average", SqlDbType.Real).Value = AAverage.AverageDerivative
).First<int>();
and I have no idea why. If I tried to rename "historyId" in Sql text to something else, exception reports this new name. It seems like parameter definition was missing or misspelled, but list of parameters has been copy&pasted, VS IDE search command finds it, prefix "#" does not matter...
Sure I can live with my working version, but I'm learning EF and it tease me I'm not able to solve this

You were sending the sql parameter as value directly.
When you did this
new SqlParameter("historyId", SqlDbType.Int).Value = AAverage.CashFlowRelevantHistoryId
You actually sent a value of AAverage.CashFlowRelevantHistoryId, not a SqlParameter.
Try changing it with this and see if it works.
AAverage.Id = ADbContext.Database.SqlQuery<int>(
cmdText.ToString(),
new SqlParameter("historyId", AAverage.CashFlowRelevantHistoryId),
new SqlParameter("nodeId", AAverage.CashNodeId),
new SqlParameter("denomId", AAverage.DenominationId),
new SqlParameter("dayId", AAverage.CashFlowDayCategoryId),
new SqlParameter("hour", AAverage.Hour),
new SqlParameter("type", AAverage.ValueType),
new SqlParameter("average", AAverage.AverageDerivative)
).First<int>();
Or this
AAverage.Id = ADbContext.Database.SqlQuery<int>(
cmdText.ToString(),
new SqlParameter("historyId", SqlDbType.Int) { Value = AAverage.CashFlowRelevantHistoryId },
new SqlParameter("nodeId", SqlDbType.Int) { Value = AAverage.CashNodeId },
new SqlParameter("denomId", SqlDbType.Int) { Value = AAverage.DenominationId },
new SqlParameter("dayId", SqlDbType.Int) { Value = AAverage.CashFlowDayCategoryId },
new SqlParameter("hour", SqlDbType.Int) { Value = AAverage.Hour },
new SqlParameter("type", SqlDbType.Int) { Value = AAverage.ValueType },
new SqlParameter("average", SqlDbType.Real) { Value = AAverage.AverageDerivative }
).First<int>();

Related

SitecoreTypeCreationContext throws exception after GlassMapper upgrade

I'm getting exception:
Inner Exception: Object reference not set to an instance of an object.
at Glass.Mapper.AbstractService.InstantiateObject(AbstractTypeCreationContext abstractTypeCreationContext)
At InstantiateObject the creation context it's not null, the item it's populated.
If I add the typeOf(TItem) then it crashes there at TItem cast, if I comment then it crashes at instatinate.
I tried to remove ConstructorParameter but even on that case it's crashing
The code before upgrade:
var creationContext = new SitecoreTypeCreationContext
{
SitecoreService = sitecoreContext,
RequestedType = typeof(TItem),
ConstructorParameters = new object[0],
Item = item,
InferType = false,
IsLazy = true,
Parameters = new Dictionary<string, object>()
};
var result = sitecoreContext.InstantiateObject(creationContext) as TItem;
The code after upgrade
var creationContext = new SitecoreTypeCreationContext
{
SitecoreService = mvcContext.SitecoreService,
Item = item,
Parameters = new Dictionary<string, object>(),
Options = new GetOptions()
{
//Type = typeof(TItem),
InferType = false,
Lazy = LazyLoading.Enabled,
ConstructorParameters = new List<ConstructorParameter>()
}
};
var result= mvcContext.SitecoreService.InstantiateObject(creationContext) as TItem;
I missed maybe a configuration or RequestedType it's not equal Option.Type?

LINQ - extract properties values into arrays

I have an List of objects and I need to get the values of each property into arrays without iterating the list more than once.
Here is the current code.
I can't seem to figure out if I can do this using Linq and only iterate the list once.
var numberOfItems = invoiceItemNotes.Count;
var postingRcNum = new decimal [numberOfItems];
var postingLocNum = new decimal[numberOfItems];
var invoiceNum = new decimal[numberOfItems];
var orderItemLineNum = new decimal[numberOfItems];
var seqNum = new decimal[numberOfItems];
var text = new string[numberOfItems];
int index = 0;
foreach (var invoiceItemNote in invoiceItemNotes)
{
postingRcNum[index] = invoiceItemNote.POSTING_RC_NUM;
postingLocNum[index] = invoiceItemNote.POSTING_LOC_NUM;
invoiceNum[index] = invoiceItemNote.INVOICE_NUM;
orderItemLineNum[index] = invoiceItemNote.ORDER_ITEM_LINE_NUM;
seqNum[index] = invoiceItemNote.SEQ_NUM;
text[index] = invoiceItemNote.TEXT;
index++;
}
using (var cmd = connection.CreateCommand())
{
cmd.CommandType = CommandType.StoredProcedure;
cmd.CommandText = InvoiceInsertCommands.InsertItemNote;
cmd.BindByName = true;
cmd.UpdatedRowSource = UpdateRowSource.None;
cmd.ArrayBindCount = numberOfItems;
cmd.Parameters.Add(InvoiceItemNoteParameters.PostingRcNum, OracleDbType.Decimal, postingRcNum, ParameterDirection.Input);
cmd.Parameters.Add(InvoiceItemNoteParameters.PostingLocNum, OracleDbType.Decimal, postingLocNum, ParameterDirection.Input);
cmd.Parameters.Add(InvoiceItemNoteParameters.InvoiceNum, OracleDbType.Decimal, invoiceNum, ParameterDirection.Input);
cmd.Parameters.Add(InvoiceItemNoteParameters.OrderItemLineNum, OracleDbType.Decimal, orderItemLineNum, ParameterDirection.Input);
cmd.Parameters.Add(InvoiceItemNoteParameters.SeqNum, OracleDbType.Decimal, seqNum, ParameterDirection.Input);
cmd.Parameters.Add(InvoiceItemNoteParameters.Text, OracleDbType.Varchar2, text, ParameterDirection.Input);
cmd.ExecuteNonQuery();
}
Simple.
object[] invoiceItemNotes = new object[10];
int index = 0;
var invoiceItemNote = invoiceItemNotes[index];

How can I create a MetadataWorkspace using metadata loading delegates?

I followed this example Changing schema name on runtime - Entity Framework where I can create a new EntityConnection from a MetaDataWorkspace that I then use to construct a DbContext with a different schema, but I get compiler warnings saying that RegisterItemCollection method is obsolete and to "Construct MetadataWorkspace using constructor that accepts metadata loading delegates."
How do I do that? Here is the code that is working but gives the 3 warnings for the RegsiterItemCollection calls. I'm surprised it works since warning says obsolete not just deprecated.
public static EntityConnection CreateEntityConnection(string schema, string connString, string model)
{
XmlReader[] conceptualReader = new XmlReader[]
{
XmlReader.Create(
Assembly
.GetExecutingAssembly()
.GetManifestResourceStream(model + ".csdl")
)
};
XmlReader[] mappingReader = new XmlReader[]
{
XmlReader.Create(
Assembly
.GetExecutingAssembly()
.GetManifestResourceStream(model + ".msl")
)
};
var storageReader = XmlReader.Create(
Assembly
.GetExecutingAssembly()
.GetManifestResourceStream(model + ".ssdl")
);
//XNamespace storageNS = "http://schemas.microsoft.com/ado/2009/02/edm/ssdl"; // this would not work!!!
XNamespace storageNS = "http://schemas.microsoft.com/ado/2009/11/edm/ssdl";
var storageXml = XElement.Load(storageReader);
foreach (var entitySet in storageXml.Descendants(storageNS + "EntitySet"))
{
var schemaAttribute = entitySet.Attributes("Schema").FirstOrDefault();
if (schemaAttribute != null)
{
schemaAttribute.SetValue(schema);
}
}
storageXml.CreateReader();
StoreItemCollection storageCollection =
new StoreItemCollection(
new XmlReader[] { storageXml.CreateReader() }
);
EdmItemCollection conceptualCollection = new EdmItemCollection(conceptualReader);
StorageMappingItemCollection mappingCollection =
new StorageMappingItemCollection(
conceptualCollection, storageCollection, mappingReader
);
//var workspace2 = new MetadataWorkspace(conceptualCollection, storageCollection, mappingCollection);
var workspace = new MetadataWorkspace();
workspace.RegisterItemCollection(conceptualCollection);
workspace.RegisterItemCollection(storageCollection);
workspace.RegisterItemCollection(mappingCollection);
var connectionData = new EntityConnectionStringBuilder(connString);
var connection = DbProviderFactories
.GetFactory(connectionData.Provider)
.CreateConnection();
connection.ConnectionString = connectionData.ProviderConnectionString;
return new EntityConnection(workspace, connection);
}
I was able to get rid of the 3 warning messages. Basically it wants you to register the collections in the constructor of the MetadataWorkspace.
There are 3 different overloads for MetadataWorkspace, I chose to use the one which requires to to supply a path (array of strings) to the workspace metadata. To do this I saved readers to temp files and reloaded them.
This is working for me without any warnings.
public static EntityConnection CreateEntityConnection(string schema, string connString, string model) {
var conceptualReader = XmlReader.Create(Assembly.GetExecutingAssembly().GetManifestResourceStream(model + ".csdl"));
var mappingReader = XmlReader.Create(Assembly.GetExecutingAssembly().GetManifestResourceStream(model + ".msl"));
var storageReader = XmlReader.Create(Assembly.GetExecutingAssembly().GetManifestResourceStream(model + ".ssdl"));
XNamespace storageNS = "http://schemas.microsoft.com/ado/2009/11/edm/ssdl";
var storageXml = XElement.Load(storageReader);
var conceptualXml = XElement.Load(conceptualReader);
var mappingXml = XElement.Load(mappingReader);
foreach (var entitySet in storageXml.Descendants(storageNS + "EntitySet")) {
var schemaAttribute = entitySet.Attributes("Schema").FirstOrDefault();
if (schemaAttribute != null) {
schemaAttribute.SetValue(schema);
}
}
storageXml.Save("temp.ssdl");
conceptualXml.Save("temp.csdl");
mappingXml.Save("temp.msl");
MetadataWorkspace workspace = new MetadataWorkspace(new List<String>(){
#"temp.csdl",
#"temp.ssdl",
#"temp.msl"
}
, new List<Assembly>());
var connectionData = new EntityConnectionStringBuilder(connString);
var connection = DbProviderFactories.GetFactory(connectionData.Provider).CreateConnection();
connection.ConnectionString = connectionData.ProviderConnectionString;
return new EntityConnection(workspace, connection);
}
Not wanting to create temp files which slows the process down, I found an alternate answer to this is fairly simple. I replaced these lines of code -
//var workspace2 = new MetadataWorkspace(conceptualCollection, storageCollection, mappingCollection);
var workspace = new MetadataWorkspace();
workspace.RegisterItemCollection(conceptualCollection);
workspace.RegisterItemCollection(storageCollection);
workspace.RegisterItemCollection(mappingCollection);
with this one line of code -
var workspace = new MetadataWorkspace(() => conceptualCollection, () => storageCollection, () => mappingCollection);
and that works fine.

MiniProfiler - ProfiledDbDataAdapter

Trying to get MiniProfiler to profile loading a DataTable via a Stored Proc
// Use a DbDataAdapter to return data from a SP using a DataTable
var sqlConnection = new SqlConnection(#"server=.\SQLEXPRESS;database=TestDB;Trusted_Connection=True;");
DbConnection connection = new StackExchange.Profiling.Data.ProfiledDbConnection(sqlConnection, MiniProfiler.Current);
var table = new DataTable();
DbDataAdapter dataAdapter = new SqlDataAdapter("GetCountries", sqlConnection);
ProfiledDbDataAdapter prdataAdapter = new ProfiledDbDataAdapter(dataAdapter, null);
// null reference exception here - SelectCommand is null
prdataAdapter.SelectCommand.CommandType = CommandType.StoredProcedure;
prdataAdapter.SelectCommand.Parameters.Add(new SqlParameter("#countryID", 2));
prdataAdapter.Fill(table);
ViewBag.table = table;
Problem: Null reference exception on SelectCommand
Please ignore lack of usings / disposing
I can successfully profile using ProfiledDbCommand to a SP:
// call a SP from DbCommand
var sqlConnection2 = new SqlConnection(#"server=.\SQLEXPRESS;database=TestDB;Trusted_Connection=True;");
DbConnection connection2 = new StackExchange.Profiling.Data.ProfiledDbConnection(sqlConnection2, MiniProfiler.Current);
if (connection2 != null)
{
using (connection2)
{
try
{
// Create the command.
DbCommand command = new SqlCommand();
ProfiledDbCommand prcommand = new ProfiledDbCommand(command, connection2, null);
prcommand.CommandType = CommandType.StoredProcedure;
prcommand.CommandText = "dbo.GetCountries";
prcommand.Parameters.Add(new SqlParameter("#countryID", 3));
prcommand.Connection = connection2;
//command.CommandText = "SELECT Name FROM Countries";
//command.CommandType = CommandType.Text;
// Open the connection.
connection2.Open();
// Retrieve the data.
DbDataReader reader = prcommand.ExecuteReader();
while (reader.Read())
{
var text = reader["Name"];
result += text + ", ";
}
}
catch (Exception ex)
{
}
}
}
Edit1:
This works:
// 2) SqlConnection, SqlDataAdapter.. dataAdapter command - works
var sqlConnection = new SqlConnection(#"server=.\SQLEXPRESS;database=TestDB;Trusted_Connection=True;");
var table = new DataTable();
//var dataAdapter = new SqlDataAdapter("GetCountries", sqlConnection);
var dataAdapter = new SqlDataAdapter("select * from countries", sqlConnection);
//dataAdapter.SelectCommand.CommandType = CommandType.StoredProcedure;
//dataAdapter.SelectCommand.Parameters.AddWithValue("#countryID", 2);
dataAdapter.Fill(table);
This doesn't DataTable.. but does with DataSet
var sqlConnection = new SqlConnection(#"server=.\SQLEXPRESS;database=TestDB;Trusted_Connection=True;");
DbConnection connection = new ProfiledDbConnection(sqlConnection, MiniProfiler.Current);
DbDataAdapter dataAdapter = new SqlDataAdapter("select * from countries", sqlConnection);
ProfiledDbDataAdapter prdataAdapter = new ProfiledDbDataAdapter(dataAdapter, null);
var table = new DataTable();
var dataset = new DataSet();
// Doesn't work
//prdataAdapter.Fill(table);
// Does work
prdataAdapter.Fill(dataset);
It turns out that though ProfiledDbDataAdapter inherited from DbDataAdapter, it did not override the default functionality of DbDataAdapter.Fill(DataTable), leading to the errors that you saw.
I fixed this in the MiniProfiler code. Fix is available in nuget, version 3.0.10-beta7 and higher.
I have tested this with your code from above and it works for me:
DbConnection connection =
new ProfiledDbConnection(sqlConnection, MiniProfiler.Current);
var sql = "select * from countries";
DbDataAdapter dataAdapter = new SqlDataAdapter(sql, sqlConnection);
ProfiledDbDataAdapter prdataAdapter = new ProfiledDbDataAdapter(dataAdapter);
var table = new DataTable();
dataAdapter.Fill(table); // this now works

alias with space in columns using linq and gridview to export excel

I need to export Excel and I'm using MVC4
This is my code
var co = from c in context.AN_COMPANY
orderby c.COMPANY_DESCR
select c;
List<AN_COMPANY_EXT> societa_list = new List<AN_COMPANY_EXT>();
foreach (var o in co)
{
AN_COMPANY_EXT c_ex = new AN_COMPANY_EXT(o);
societa_list.Add(c_ex);
}
GridView gv = new GridView();
gv.DataSource = (from d in societa_list
select new { Codice = d.ID_COMPANY, Descrizione = d.COMPANY_DESCR, SAP_Alias = d.COMPANY_SAP_ALIAS, Booking_Company = d.IS_BOOKING_COMPANY });
gv.DataBind();
Response.Buffer = true;
Response.AddHeader("content-disposition", "attachment; filename=AnagraficaSocieta.xls");
Response.ContentType = "application/ms-excel";
Response.Charset = "";
StringWriter sw = new StringWriter();
HtmlTextWriter htw = new HtmlTextWriter(sw);
gv.RenderControl(htw);
Response.Output.Write(sw.ToString());
Response.Flush();
Response.End();
return RedirectToAction("Index");
How can I set column name with a space, for example "SAP ALIAS" instead of SAP_ALIAS?

Resources