Convert GUID array to int array - c#

I'm using linq query to create my collection based on it's id which is a guid.I've an item which can be associated to 1 or more products.What I need is to show all the productnames associated to that item and other datas like name,summary,date aswell.My issue here is when i try to use the variable i which is a guid in my array it throws error that Guid cannot be converted to int.I'm very sure that I've to convert my Guid array to int array but not sure how to implement it. below is my code.
foreach( Guid i in itemid)
{
var vals = from r in datacontext.ItemTable_s where r.itemID == i select r;
ItemTable_s[] tempdata = vals.ToArray<.ItemTable_s>();
Facet[] ftemp= new Facet[tempdata.Length];
ItemImage image = null;
string s1="";
for (int iv = 0; iv < tempdata.Length; iv++)
{
s1 += tempdata[i].productname + "\n";
}
ftemp[3] = new facet("Productname",facettype.text,s1);
collection.AddItem( tempdata[i].ItemName, null, null,
new ItemImage(new Uri(-tempdata[i].location))
);
}
In my above code tempdata[i] is where i get error msg saying guid cannot be converted to int implicitly.How do i fix this is there any other better approach?

Change your logic. Instead of using a foreach, use an int for statement. Then access the itemid's from the array. Something like this:Something like this:
for( int i=0; i<items.Count; i++)
{
...
var vals = from r in datacontext.ItemTable_s where r.itemID == itemid[i] select r;
...
s1 += tempdata[i].productname + "\n";
}
Didn't try the code, but I hope you'll get the idea...

(A GUID is 128 bits, so it cannot safely be converted into a 32-bit integer.)
A better option might be to use a Dictionary<Guid, ItemTable_s>. Then you can still use GUIDs to index it.
var tempdata = new Dictionary<Guid, ItemTable_s>;
foreach(var anItem in datacontext.ItemTable_s)
{
tempdata.Add(anItem.ItemID, anItem);
}
Then the line that's currently raising an exception (s1 += tempdata[i].productname + "\n";) should work as-is.
This will also make your itemid array unnecessary. Alternatively you could keep the two arrays you're using. Then you would have to change that line to:
s1 += tempdata[itemid.IndexOf(i)].productname + "\n";
It looks like that is what you were intending to do. But that will be much slower than using a dictionary. It means you'll be doing a sequential search of the itemid array every time you need to figure out where an entry is in tempdata.

A GUID looks like this
7c9e6679-7425-40de-944b-e07fc1f90ae7
As you can see there is not an Int Representation of that character. your Facet Constructor would need to take a GUID instead of an int.

Related

Searching a two dimensional object array in c#

I have declared a two-dimensional object array as
object[,] sectionOpenings = new object[20, 4];
The first column is populated with string types, whilst the remaining three columns are all integers.
I wish to do a quick search to find a row with a matching string in the first column and have tried this
var first = Array.Find(sectionOpenings, p => p == "homedepot");
I get the following error:
Error CS0411 The type arguments for method 'Array.Find(T[], Predicate)' cannot be inferred from the usage. Try specifying the type arguments explicitly.
Any suggestions?
You can alter your code a bit to get what you what:
var first = Array.Find(sectionOpenings, p => p[0] == "homedepot");
this will look in each array row, the first column p[0] == "homedepot"
edit:
my bad, I thought about jagged arrays
Well its not a one liner, but you can create a method like so:
public static int GetMatchingRow(object[,] myArr, string findMe)
{
for (int i = 0; i < myArr.GetLength(0); i++)
{
if (myArr[i, 0] is string && myArr[i, 0] as string == findMe)
return i;
}
return -1;
}
I would suggest changing to a dictionary to ensure type safety- like so:
var sectionOpenings = new Dictionary<string, List<int>>();
sectionOpenings.TryGetValue("homedepot", out var result);
However, if you are stuck using a 2D array, you'll likely have to do this in two steps. One, you'll have to find the matching column. Two, you'll have to retrieve the column. Something like this could work:
object[,] sectionOpenings = new object[20, 4];
var firstRowMatch = Enumerable
.Range(0, sectionOpenings.GetLength(0)) // Gets row indices
.Where(row => sectionOpenings[row, 0].ToString().Equals("homedepot"))
.First();
var result = Enumerable
.Range(0, sectionOpenings.GetLength(1)) // Gets column indices
.Select(column => sectionOpenings[firstRowMatch, column])
.ToArray();
With this example, you will likely have to add some type checks and null checks to make sure that this doesn't explode with a NullReferenceException.
This is adapted from returning a whole column from a 2D array and getting the number of columns/rows from a 2D array on stack overflow.
PS. This assumes you're using System.Linq

I need to use a for-loop to find strings in an array-list that have the same word in them

I need to find a way to use a for-loop to find how many strings that are the same word in the same array-list. I need to use the for-loop because everytime it loops and finds another word that is the same I want to add it to an int variable :the following is the code that have tried to use but it didn;t work. variable bedrooms kept saying that it is 0 when it is not
foreach (string row in RoomType) // RoomType is the ArrayList
{
if (row.Equals("Bedroom"))
{
bedrooms++;
}
}
This code works, which is based on your code. I am assuming that you are probably doing something in your code where bedrooms is getting re-declared during the looping. This is a guess though.
var RoomType = new ArrayList();
var bedrooms = 0;
RoomType.Add("workflow");
RoomType.Add("Bedroom");
RoomType.Add("Bedroom");
foreach (string row in RoomType) // RoomType is the ArrayList
{
if (row.Equals("Bedroom"))
{
bedrooms++;
}
}
Console.WriteLine(bedrooms);
A different way:
var row = RoomType.Cast<string>().ToArray();
var count = row.Aggregate(0, (c, i) => (i.Equals("Bedroom")) ? ++c : c);
If you are not compelled to use a loop, you could try starting with this:
int bedrooms = RoomType.ToArray().Count(row => row.Equals("Bedroom"));
If you are compelled to use a loop, then please post a bit more of the code so that we can see where and how these objects are being set.

How can I pass an unkown number of arguments to C#'s "Database.Open("DatabaseName").Query()" method?

I have tried Googling to find a solution, but all I get is totally irrelevant results or results involving 2 dimensional arrays, like the one here: http://social.msdn.microsoft.com/Forums/vstudio/en-US/bb4d54d3-14d7-49e9-b721-db4501db62c8/how-does-one-increment-a-value-in-a-two-dimensional-array, which does not apply.
Say I have this declared:
var db = Database.Open("Content");
var searchTerms = searchText.Split('"').Select((element, index) => index % 2 == 0 ? element.Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries) : new string[] { element }).SelectMany(element => element).ToList();
int termCount = searchTerms.Count;
(Note: All that you really need to know about searchTerms is that it holds a number of search terms typed into a search bar by the user. All the LINQ expression is doing is ensuring that text wrapped in qoutes is treated as a single search term. It is not really necessary to know all of this for the purpose of this question.)
Then I have compiled (using for loops that loop for each number of items in the searchTerms list) a string to be used as a SELECT SQL query.
Here is an example that shows part of this string being compiled with the #0, #1, etc. placeholders so that my query is parameterized.
searchQueryString = "SELECT NULL AS ObjectID, page AS location, 'pageSettings' AS type, page AS value, 'pageName' AS contentType, ";
for (int i=0; i<termCount; i++)
{
if(i != 0)
{
searchQueryString += "+ ";
}
searchQueryString += "((len(page) - len(replace(UPPER(page), UPPER(#" + i + "), ''))) / len(#" + i + ")) ";
}
searchQueryString += "AS occurences ";
(Note: All that you really need to know about the above code is that I am concatenating the incrementing value of i to the # symbol to dynamically compile the placeholder value.)
All of the above works fine, but later, I must use something along the lines of this (only I don't know how many arguments I will need until runtime):
foreach (var row in db.Query(searchQueryString, searchTerms[0]))
{
#row.occurences
}
(For Clarification: I will need a number of additional arguments (i.e., in addition to the searchQueryString argument) equal to the number of items in the searchTerms list AND they will have to be referencing the correct index (effectively referencing each index from lowest to highest, in order, separated by commas, of course.)
Also, I will, of course need to use an incrementing value to reference the appropriate index of the list, if I can even get that far, and I don't know how to do that either. Could I use i++ somehow for that?
I know C# is powerful, but maybe I am asking too much?
Use params keyword for variable numbers of parameters. With params, the arguments passed to a any function are changed by the compiler to elements in a temporary array.
static int AddParameters(params int[] values)
{
int total = 0;
foreach (int value in values)
{
total += value;
}
return total;
}
and can be called as
int add1 = AddParameters(1);
int add2 = AddParameters(1, 2);
int add3 = AddParameters(1, 2, 3);
int add4 = AddParameters(1, 2, 3, 4);
//-----------Edited Reply based on comments below---
You can use something like this to be used with SQL
void MYSQLInteractionFunction(String myConnectionString)
{
String searchQueryString = "SELECT NULL AS ObjectID, page AS location, 'pageSettings' AS type, page AS value, 'pageName' AS contentType, ";
SqlConnection myConnection = new SqlConnection(myConnectionString);
SqlCommand myCommand = new SqlCommand(searchQueryString, myConnection);
myConnection.Open();
SqlDataReader queryCommandReader = myCommand.ExecuteReader();
// Create a DataTable object to hold all the data returned by the query.
DataTable dataTable = new DataTable();
// Use the DataTable.Load(SqlDataReader) function to put the results of the query into a DataTable.
dataTable.Load(queryCommandReader);
Int32 rowID = 0; // or iterate on your Rows - depending on what you want
foreach (DataColumn column in dataTable.Columns)
{
myStringList.Add(dataTable.Rows[rowID][column.ColumnName] + " | ");
rowID++;
}
myConnection.Close();
String[] myStringArray = myStringList.ToArray();
UnlimitedParameters(myStringArray);
}
static void UnlimitedParameters(params string[] values)
{
foreach (string strValue in values)
{
// Do whatever you want to do with this strValue
}
}
I'm not sure I quite understand what you need from the question, but it looks like you're substituting a series of placeholders in the SQL with another value. If that's the case, you can use String.Format to replace the values like this:
object val = "a";
object anotherVal = 2.0;
var result = string.Format("{0} - {1}", new[] { val, anotherVal });
This way, you can substitute as many values as you need by simply creating the arguments array to be the right size.
If you're creating a SQL query on the fly, then you need to be wary of SQL injection, and substituting user-supplied text directly into a query is a bit of a no-no from this point of view. The best way to avoid this is to use parameters in the query, which automatically then get sanitised to prevent SQL injection. You can still use a 'params array' argument though, to achieve what you need, for example:
public IDataReader ExecuteQuery(string sqlQuery, params string[] searchTerms)
{
var cmd = new SqlCommand { CommandText = sqlQuery };
for (int i = 0; i < searchTerms.Length; i++)
{
cmd.Parameters.AddWithValue(i.ToString(), searchTerms[i]);
}
return cmd.ExecuteReader();
}
obviously, you could also build up the sql string within this method if you needed to, based on the length of the searchTerms array
Well, for how complex the question probably seemed, the answer ended up being something pretty simple. I suppose it was easy to overlook because I had never done this before and others may have thought it too obvious to be what I was looking for. However, I had NEVER tried to pass a variable length of parameters before and had no clue if it was even possible or not (okay, well I guess I knew it was possible somehow, but could have been very far from my method for all I knew).
In any case, I had tried:
foreach (var row in db.Query(searchQueryString, searchTerms)) //searchTerms is a list of strings.
{
//Do something for each row returned from the sql query.
}
Assuming that if it could handle a variable length number of arguments (remember each argument passed after the first in the Database.Query() method is treated as fillers for the placeholders in the query string (e.g., #0, #1, #2, etc.) it could accept it from a list if it could from an array.
I couldn't really have been any more wrong with that assumption, as passing a list throws an error. However, I was surprised when I finally broke down, converted the list to an array, and tried passing the array instead of the list.
Indeed, and here is the short answer to my original question, if I simply give it an array it works easily (a little too easily, which I suppose is why I was so sure it wouldn't work):
string[] searchTermsArray = searchTerms.ToArray();
foreach (var row in db.Query(searchQueryString, searchTermsArray)) //searchTermsArray is an array of strings.
{
//Do something for each row returned from the sql query.
}
The above snippet of code is really all that is needed to successfully answer my original question.

c# Arrays - Index Out of Range Exception

I am getting indexoutofrangeexception (see ----> pointer for the line generating the error down below in the code). The program loops through the header and line item records in a dataset tables. The tables have a relationship. My sample data has 2 headers, each with 2 lines. The progam has two loops, the first one loops through the header records and the second one loops through the child records of the header.
Part of the program:
// ***** PO Header and Line
int ln;
ln = 0;
// Create an eConnect PO Header node object
taGLTransactionHeaderInsert jeh = new taGLTransactionHeaderInsert();
// Create an array for lineitems
taGLTransactionLineInsert_ItemsTaGLTransactionLineInsert[] lineitems = new taGLTransactionLineInsert_ItemsTaGLTransactionLineInsert[ln];
foreach (DataRow dtrHDR in ds.Tables["Header"].Rows)
{
Array.Clear(lineitems, 0, ln);
jeh.BACHNUMB = "Sheraz";
jeh.JRNENTRY = jenoint;
jeh.REFRENCE = dtrHDR["Reference"].ToString();
jeh.SOURCDOC = dtrHDR["AvantisJE"].ToString();
jeh.USERID = System.Environment.UserName;
jeh.TRXDATE = System.DateTime.Now.ToString();
ln = 0;
foreach (DataRow dtrLine in dtrHDR.GetChildRows("HdrLine"))
{
// Populate the elements of the taPoLIne_ItemsTaPOLine XML node
taGLTransactionLineInsert_ItemsTaGLTransactionLineInsert jel = new taGLTransactionLineInsert_ItemsTaGLTransactionLineInsert();
jel.BACHNUMB = jeh.BACHNUMB;
jel.JRNENTRY = jeh.JRNENTRY;
jel.ACTNUMST = dtrLine["GreatPlains"].ToString();
jel.DEBITAMT = Convert.ToDecimal(dtrLine["Debit"].ToString());
//Avantis Inv Trx Key
jel.ORDOCNUM = dtrLine["AvantisJE_Line"].ToString();
// Avantis GL Trx Type
jel.ORTRXDESC = dtrLine["transactiontypename"].ToString();
//Add POLine to an Array
lineitems[ln] = jel; ----------------> I get an error here!
ln = ln + 1;
Array.Resize(ref lineitems, ln + 1);
}
}
You are accessing an index that doesn't yet exist.
//Add POLine to an Array
lineitems[ln] = jel; ----------------> I get an error here!
ln = ln + 1;
Array.Resize(ref lineitems, ln + 1);
You need to change the order to :
//Add POLine to an Array
Array.Resize(ref lineitems, ln + 1);
lineitems[ln] = jel; ----------------> should be fixed, no error here!
ln = ln + 1;
EDIT: Now that the immediate problem is out of the way, on to a better implementation.
Arrays are of a fixed sized, resizing an array is an expensive operation (basically it entails creating a copy with a new size). typically you would use these after identifying a performance bottle neck. In most cases it would be much better to use a List.
I'd recommend changing this line:
// Create an array for lineitems
taGLTransactionLineInsert_ItemsTaGLTransactionLineInsert[] lineitems =
new taGLTransactionLineInsert_ItemsTaGLTransactionLineInsert[ln];
to:
var lineitems = new List<taGLTransactionLineInsert_ItemsTaGLTransactionLineInsert>();
and then to add to it you simply do
lineitems.Add(jel);
to iterate over them would be:
for (var ln in lineitems) {
// whatever you want to do with a line.
}
to acccess a specific item by index would be:
lineitems.Item(i); // get the ith item in the list.
This is because you created an array with 0 elements and try to insert an element on position 0. This will not work. You can fix it by declaring the array with a size of 1 to begin with:
// Create an array for lineitems
taGLTransactionLineInsert_ItemsTaGLTransactionLineInsert[] lineitems = new taGLTransactionLineInsert_ItemsTaGLTransactionLineInsert[1];
However, resizing an array on the fly is not the idiomatic .NET way of doing this. You could use a List<T>, which takes care of resizing for you, and leaving you with cleaner code and possibly better performance.
It appears that you're trying to increase the size of the array by setting a value, like you might do in JavaScript. C# arrays are not like that. You need to create them at the size you want them to be when finished.
Alternately, you could use a List object, using the Add() method to put new content into the list.
lineitems is obviously not the same size as the row collection returned by dtrHDR.GetChildRows("HdrLine"). You are creating an array of zero elements and then trying to index into it. If you want it to match the size of dtrHDR.GetChildRows("HdrLine") then you need to call that first and initialize the array after you can get the count.
Instead of using an array why don't you use a List<T> and just push items onto it? No need to worry about IndexOutOfRange exceptions anymore.
You need to initialize the array before putting anything in to it. call the .resize first.
those lines are the problem
int ln;
ln = 0;
// Create an array for lineitems
taGLTransactionLineInsert_ItemsTaGLTransactionLineInsert[] lineitems = new taGLTransactionLineInsert_ItemsTaGLTransactionLineInsert[ln];
You create table of 0 elements.
You have an off-by-one error in your program:
int ln = 0
.
.
.
taGLTransactionLineInsert_ItemsTaGLTransactionLineInsert[] lineitems = new taGLTransactionLineInsert_ItemsTaGLTransactionLineInsert[ln];
.
.
.
lineitems[ln] = jel;
You are initializing an array of 0 elements, then trying to set the first element (element[0]) to a value.

Perserving Array from AnonymousType

I looked online for some references but didn't have too much luck. Hopefully it's just some simple thing I'm overlooking, but in my code I'm looping through the participant list and storing the queried results into the array. As you can tell, my foreach statement will just add the last element of the array since the first one is replaced.
How can I just add the value to the next array index. So, if there are [2] in the array, how can I make sure that this.physEntityPhysicalLeftEntityIDs contains [2] instead of just always [1]? If I need to clarify, let me know.
if (leftParticipants.Length >= 0) // Check to see if LeftParticipants exists
{
for (int c = 0; c < leftParticipants.Length; c++)
{
var l_entityIDs =
from BioList in o_data.Descendants(bp + "physicalEntityParticipant")
where BioList.Attribute(rdf + "ID").Value == leftParticipants[c].TrimStart('#')
select new
{
o_entityIDs = BioList.Elements(bp + "PHYSICAL-ENTITY")
.Select(entityID => entityID.Attribute(rdf + "resource").Value).ToArray()
};
foreach (var entity in l_entityIDs)
{
this.physEntityPhysicalLeftEntityIDs = entity.o_entityIDs; // Set SmallMolecules from Left
}
}
}
If physEntityPhysicalLeftEntityIDs is an array, you'll need to initialize an index variable and increment it each time through the foreach loop:
int destIndex = 0;
foreach (var entity in l_entityIDs)
{
this.physEntityPhysicalLeftEntityIDs[destIndex] = entity.o_entityIDs; // Set SmallMolecules from Left
++destIndex;
}
That assumes that you've allocated enough space in the array. If there are more items than will fit in the array, you're going to get an index out of bounds error.
To make sure there's enough space in the array, you can allocate it before the loop above:
this.physEntityPhysicalLeftEntityIds = new int[l_entityIDs.Count()];
Replace int in that line with the proper type (you didn't say what type is being stored in the array).
Well if you want to treat it like an array/list, all you have to do is
l_enityIDs.ToList()
and then .Add(new {o_entityIDs = foo})
If you want to add it to the IEnumerable, that requires an extension method that returns everything in the source enumberable, and a yield statement adding on your next value.

Categories