Index out of range exception when using this query from C# - c#

I am using a calculation in my SQL query. How can I use that calculated field in C#? When I try, I get an index out of range exception.
My query is:
Select OwnerCompanyLog.olog_name,inlt_companyid,inlt_childcompid,inlt_effectinterest,inlt_percent,inlt_sharetype,inlt_shares,inlt_childbase,inlt_effdate,
((inlt_percent * inlt_effectinterest)/100)eff
from InterestLogTable
INNER JOIN OwnerCompanyLog
ON
InterestLogTable.inlt_childcompid = OwnerCompanyLog.olog_companyid
where inlt_companyid=5
Order By inlt_childcompid
I want to use inlt_percent * inlt_effectinterest)/100 in my C# code:
entity.ParentCompany = new List<Company>();
while (parentCompanyReader.Read())
{
ParentCompany.Effect = parentCompanyReader["eff"].ToString();
entity.ParentCompany.Add(ParentCompany);
}
parentCompanyReader.Close();
But I got the error above.

the problem is only with calculated field. The above comment is absolutely correct. It could be your parentCompanyReader class that has the error. Meanwhile could you try few things to confirm the error.
Move the eff column to some middle. It could be that your parentCompanyReader would not be able to deal with only a limited number of column.
Also what is "eff" here, a column ? Also put a AS after the calculated column.
Select (inlt_percent * inlt_effectinterest)/100)eff AS EFF, OwnerCompanyLog.olog_name,inlt_companyid,inlt_childcompid,inlt_effectinterest,inlt_percent,inlt_sharetype,inlt_shares,inlt_childbase,inlt_effdate
Note : these are just arrows in dark !

Try to use it with index rather than column name .
while (parentCompanyReader.Read())
{
ParentCompany.Effect = Convert.ToInt32(parentCompanyReader[5]);
entity.ParentCompany.Add(ParentCompany);
}
parentCompanyReader.Close();
Im assuming that the calculated field returns an integer
and also make sure u use using statement so that incase if there is an error then connection will be closed and disposed

Related

how to get max id from a table using linq

I have a table Estimation which has an column EstimationNo,i am trying to get the max EstimationNo like this-
var result = cont.SalesEstimateCont.Where(x => x.Org_ID == CurrentOrgId);
var estimationMaxNo = result.Any() ? result.Max(x => x.EstimateNo) + 1 : 1;
var DigitalEstimate = new SalesEstimate()
{
EstimateNo=estimationMaxNo;
};
cont.Estimate.Add(DigitalEstimate );
cont.Savechanges();
but the problem is, if same table is saving by different users at same time its saving the same EstimationNo for both users. like- 10,10
Now, how to handle this issue..please give some solution.
Best strategy is to let db engine (I assume that it is SQL Server) handle incrementing of EstimateNo field. This can be done with identity specification which can be added to normal not primary key field also.
ALTER TABLE SalesEstimateCont drop column EstimateNo
go
ALTER TABLE SalesEstimateContadd Add EstimateNo int NOT NULL IDENTITY (1,1)
Please note: if you have existing data or some data should be modified, you may need some extra effort to achieve this (i.e with temp tables and by setting IDENTITY INSERT ON)
I got a simple answer.I just had to use transacationScope class.
and lock the resource table. like this-
using (TransactionScope scope = new TransactionScope())
{
cont.Database.ExecuteSqlCommand("SELECT TOP 1 * FROM Sales__Estimate WITH (TABLOCKX, HOLDLOCK)");
var result = cont.SalesEstimateCont.Where(x => x.Org_ID == CurrentOrgId);
var estimationMaxNo = result.Any() ? result.Max(x => x.EstimateNo) + 1 : 1;
var DigitalEstimate = new SalesEstimate()
{
EstimateNo=estimationMaxNo;
};
cont.Estimate.Add(DigitalEstimate );
cont.Savechanges();
}
If you can make EstimateNo an Identity column, that is the easiest/best way to fix this. If you can change this to a Guid, that would be another easy way to fix this as PK would be unique regardless of the user.
If you can't do either of these and you must take Max() manually, you might want to consider creating another table that stores the next available number there. Then you can create a new SqlCommnand with a Serializable transaction to lock the table, update the # by 1 and select it back. If two update commands hit at the same time, only one update will run and won't let go until that connection with Serializable transaction gets closed. This allows you to select the newly updated number before the other update runs and get the now "unique" next number.
You can OrderByDescending and then Take the the first record
var estimationMaxNo = result.OrderByDescending(x => x.EstimateNo).Take(1);
It can be done in a single command. You need to set the IDENTITY property for primary id
ALTER TABLE SalesEstimateCont ADD Org_ID int NOT NULL IDENTITY (1,1) PRIMARY KEY

get and post table type using pqxx

Good day, friends. I'm using pqxx and I have some questions.
1. I have two tables:
table1 (table1_id integer) and table2 (table1_id integer, another_id integer) with relation one-to-many.
How I can easy get information in view like: table1_id, vector another_ids?
Now I use serializtion in script (string concat into "%d %d %d...") and deserialization in my c++ code.
Also I need insert value into table1. And how I can do this in one transaction?
2. I call stored procedure like
t.exec("SELECT * FROM my_proc(some_argument)");
May be exists any way to do this like in c#?
Thank you very much!
So, may be it can help someone.
In first case I find and use two ways:
1. Group concat in sql function and deserialization in c++. It fast if table2 has only table1_id and another integer.
2. I call two function: get_table1() and get_table2() with order by table1_id. And then with two pointers I create array of table1:
std::vector<Table1> table1Array;
auto ap = wrk.prepared(GetTable1FuncName).exec();
auto aps = wrk.prepared(GetTable2FuncName).exec();
auto pos = aps.begin();
for (auto row = ap.begin(); row != ap.end(); ++row) {
std::vector<Table2> table2Array;
while (pos != aps.end()
&& row["table1_id"].as(int()) == pos["table1_id"].as(int())) {
table2Array.push_back(Table2(pos["first_id"].as(int()),
pos["second_string"].as(std::string())));
++pos;
}
Table1 tb1(row["table1_id"].as(int()), row["column2"].as(int()),
row["column3"].as(int()), row["column4"].as(int()),
table2Array);
table1Array.push_back(tb1);
}
May be it is not pretty, but it's working.
Insert into database I write for one element. Firstly insert into Table1, and after several lines into Table2. After call pqxx::work.commit().
In second case Not, doesn't exists. Also remember, function always return 1 line! Be careful!

Insert into 120 columns from 120-indexed array

I have column names like this
Id
,Test
,[H01_1]
,[H01_2]
,[H01_3]
,[H01_4]
,[H01]
,[H02_1]
,[H02_2]
,[H02_3]
,[H02_4]
,[H02]
,[H03_1]
,[H03_2]
,[H03_3]
,[H03_4]
,[H03]
,[H04_1]
,[H04_2]
,[H04_3]
,[H04_4]
,[H04]
,[H05_1]
,[H05_2]
,[H05_3]
,[H05_4]
,[H05]
,[H06_1]
,[H06_2]
,[H06_3]
,[H06_4]
,[H06]
,[H07_1]
,[H07_2]
,[H07_3]
,[H07_4]
,[H07]
,[H08_1]
,[H08_2]
,[H08_3]
,[H08_4]
,[H08]
,[H09_1]
,[H09_2]
,[H09_3]
,[H09_4]
,[H09]
,[H10_1]
,[H10_2]
,[H10_3]
,[H10_4]
,[H10]
,[H11_1]
,[H11_2]
,[H11_3]
,[H11_4]
,[H11]
,[H12_1]
,[H12_2]
,[H12_3]
,[H12_4]
,[H12]
,[H13_1]
,[H13_2]
,[H13_3]
,[H13_4]
,[H13]
,[H14_1]
,[H14_2]
,[H14_3]
,[H14_4]
,[H14]
,[H15_1]
,[H15_2]
,[H15_3]
,[H15_4]
,[H15]
,[H16_1]
,[H16_2]
,[H16_3]
,[H16_4]
,[H16]
,[H17_1]
,[H17_2]
,[H17_3]
,[H17_4]
,[H17]
,[H18_1]
,[H18_2]
,[H18_3]
,[H18_4]
,[H18]
,[H19_1]
,[H19_2]
,[H19_3]
,[H19_4]
,[H19]
,[H20_1]
,[H20_2]
,[H20_3]
,[H20_4]
,[H20]
,[H21_1]
,[H21_2]
,[H21_3]
,[H21_4]
,[H21]
,[H22_1]
,[H22_2]
,[H22_3]
,[H22_4]
,[H22]
,[H23_1]
,[H23_2]
,[H23_3]
,[H23_4]
,[H23]
,[H24_1]
,[H24_2]
,[H24_3]
,[H24_4]
,[H24]
And I am trying to write a simple INSERT with dapper (SQL Server 2014).
For the Id and Test I am writing an anonymous object to put into the param but I wasn't sure whats the best way to take a 120 length int? array and insert it into the columns beginning with H
Where index 0 goes to H01_1 and index 1 goes to H01_2 ... etc
I don't want to have to write SQL that says
H01_1 = #H01_1,
H01_2 = #H01_2,
...
And then also have to make an anonymous object that does
H01_1 = array[0],
H01_2 = array[1],
...
One thing I can do is insert just Id and Test and then go back and do an UPDATE on that record. But I am still in the same scenario I was before where I don't know the best way to write an UPDATE in dapper without writing things out 120 times.
If it is possible to change your datatable structure then only follow below design
In your table you have more number of column and find out that your assigned ID as primary . So instead of using above data structure use below ..
ID test column value
01 xyz H01_1 val_H01_1
01 xyz H01_2 val_H01_2
Assign group primary key for ID,test and column..
If it is not possible for changing structure . Then create a XML from your front end data and create Stored procedure like below to excute it . If you go through with http://www.itworld.com/article/2960645/development/tsql-how-to-use-xml-parameters-in-stored-procedures.html then you will get idea.

C# and SQL System.ArgumentOutOfRangeException

I am attempting to create an application which connects to a database using sql and I am trying to create a dataview which looks at the current selected dataview and then pulls back information from another table. I have followed some guides and have gotten fairly close but I am currently getting this error:
An unhandled exception of type 'System.ArgumentOutOfRangeException'
occurred in mscorlib.dll Additional information: Index was out of
range. Must be non-negative and less than the size of the collection.
Any help would greatly be appreciated. (Visual Studio shows the error at the end of the first line below)
string PersonID = Grid1.SelectedRows[0].Cells[0].Value.ToString();
sqlDataAdapter2.SelectCommand.CommandText = "select * from Personal_Emails where PersonID=" + PersonID;
sqlDataAdapter2.Fill(dataSet21.Personal_Emails);
You need to check if something exists before you can use it.
var selectedRow = Grid1.SelectedRows[0];
var cell = selectedRow == null ? false : selectedRow.Cells.Any();
var personID = (cell) ? Grid1.SelectedRows[0].Cells[0].Value.ToString() : "";
if(!string.isNullOrEmpty(personID)
// do query stuff
string PersonID = Grid1.SelectedRows[0].Cells[0].Value.ToString();
verify if this line is returning some value <> null.
example : if the grid has no selected rows it will return error or empty value.
Have you checked that SelectedRows & Cells have a selected value? You could use the debugger and see what the values are.
Also:
You are defining PersonID as a string. Is it a string value in your database? If so, have you tried:
sqlDataAdapter2.SelectCommand.CommandText = "SELECT * FROM Personal_Emails WHERE PersonID='" + PersonID + "'";

Force autoinc field with MySqlDataAdapter/MySqlCommandBuilder

With C# and MySQL ADO.NET connector, I use MySqlDataAdapter and MySqlCommandBuilder to update a table.
Is it possible to temporarily force an autoinc field ?
DataRow row = ...
row["Id"] = 90; // force autoinc value
using (MySqlDataAdapter adapter = ...)
{
MySqlCommandBuilder builder = new MySqlCommandBuilder(adapter);
int result = adapter.Update(new DataRow[] { row });
// The inserted ID is 20 and not 90...
Yes you can, so long as you explicitly specify the value as in the code example that you provided, it will work. Off course it will fail if a duplicate value is specified.
The auto increment is only applied to an insert if you omitted the value or the value is NULL or 0 or DEFAULT.
#A.Baudouin I think you meant to say "Unfortunately, as you can see in my example above, it does not work"! Did you ever find a solution? I had exactly the same problem but found that it works OK if you use MySql Workbench to modify the value. All the Workbench does is a normal UPDATE command, so I am guessing this is a problem of MySqlAdapter, or maybe a "feature"! I ended up updating the database directly like:
MySqlHelper.ExecuteNonQuery(myConnection, "UPDATE MyTable SET Id = 90 WHERE Id = 7", null);
(or however you want to identify the correct row with WHERE). This works OK.

Categories