Ordering the row_number using LinqToSql in asp.net/C# - c#

I have set of records in a database table lets call it Components Table which is defined as follows.
The administrator can disable some of the components using disableflag which is the last column of the table. If a particular component is disabled it should not appear in the gridview of the user.
I'm getting the data from the database and presenting through the gridview as shown here, if you observe the SNo values are not in order.
The linq query that i'm using to retrieve the data is:
var gridViewResults = from results in db.Components where results.DisableFlag == false
select new { SNo = results.SNo, ComponentNames = results.Component_Name, Size = results.Size__in_MB_, Price = results.Price__in_SEK_, TotalDownloads = results.Total_Downloads, Description = results.Description };
But I want the data to be shown in order meaning with SNo to be 1, 2, 3, 4 with out dependency on the database table SNO values: for reference look at this.
I'm not able to figure out how to use the linq query to achieve this:
I have tried this query:
(db.Components.AsEnumerable().Select((iterator)=> new{iterator.SNo + 1})
But i think it is absurd. Can some one help me out on this.
Thanks in anticipation.

If you're absoutely certain you want to ignore the database numbers (why output the numbers if they don't actually correspond to anything?) you may be able to try the following:
var gridViewData = from results in db.Components
where results.DisableFlag == false
select new
{
ComponentNames = results.Component_Name,
Size = results.Size__in_MB_,
Price = results.Price__in_SEK_,
TotalDownloads = results.Total_Downloads,
Description = results.Description
};
var gridViewResults = gridViewData.AsEnumerable().Select((item, index) => new
{
SNo = index + 1,
ComponentNames = item.ComponentNames,
Size = item.Size,
Price = item.Price,
TotalDownloads = item.TotalDownloads,
Description = item.Description
});
EDIT: Alternate solution from How To Project a Line Number Into Linq Query Results
EDIT2: Fix for unsupported select by SQL: Linq error - "NotSupportedException: Unsupported overload used for query operator 'Select'"

Hi everyone here is the final answer. Joshua did all of the work. A big thanks to him. Just want to highlight the answer to anyone with the same problem for the future. If any one want to vote up please vote for Joshua
var gridViewData = from results in db.Components
where results.DisableFlag == false
select new
{
ComponentNames = results.Component_Name,
Size = results.Size__in_MB_,
Price = results.Price__in_SEK_,
TotalDownloads = results.Total_Downloads,
Description = results.Description
};
var gridViewResults = gridViewData.AsEnumerable().Select((item, index) => new
{
SNo = index + 1,
ComponentNames = item.ComponentNames,
Size = item.Size,
Price = item.Price,
TotalDownloads = item.TotalDownloads,
Description = item.Description
}).ToList();
This should work.

Related

Dynamic linq backslash in where clause

I use System.Linq.Dynamic to query entities with dynamic 'where' expressions. I'm querying object that has property "newValue" of string type. Exemplary value would be : "{\"ProcessId\":764, \"ProcessLength\":1000}".
I can't use == because I want to find all hits where the property contains "ProcessId:764", regardless on the rest of the string. The thing is, that stored string contains escape sign "\" and double quotes and I can't figure out what it should like exactly..
dbContext.Processes.Where("#newValue.Contains(\"ProcessId\":764\")") brings error, however dbContext.Processes.Where("#newValue.Contains(\":764\")") works correctly. I guess it must be something with backslashes or double quotes in my query but can't figure it out on my own..
There are two things to note here:
If you know at compile time the column that should be queried (i.e., newValue), just use standard Linq: var list = items.Where(i => i.NewValue.Contains("904")).ToList().
If you do want to use dyanmic Linq, What you'd usually want is to apply Where on some column, e.g. Where("SomeColumn.Contains("something")"), or Where("SomeColumn.Contains(#0)", new string[] {"something"}).
So, in your case, this should work: items.Where("newValue.Contains(\"904\")").
Doing Where("#newValue.Contains("something")") doesn't really make sense, since #newValue would be parsed as a string literal. See also this comment on a similiar question.
Here' a quick example:
public static void Main(string[] args)
{
var items = new []
{
new { Id = "1", Title = "ProcessId: 123"},
new { Id = "4", Title = "ProcessId: 456"},
new { Id = "7", Title = "ProcessId: 789"},
}.ToList();
// returns null, because the string "Title" doesn't contain the string "7"
var res1 = items.Where("#0.Contains(\"7\")", new string[] {"Title"}).FirstOrDefault();
// works - returns the 3rd element of the array
var res2a = items.Where("Title.Contains(#0)", new string[] {"ProcessId: 789"}).FirstOrDefault();
var res2b = items.Where("Title.Contains(\"ProcessId: 789\")").FirstOrDefault();
}
#HeyJude Thanks for the effort, but I still can't get it to work. It has somehow gone wronger and now I can't even fetch correct rows giving only ProcessId number..
Let me give you more detailed description of my setup. In the database there's a table with column "NewValue", I use this column to store json string of current (for the time of creating row in the table) representation of some object e.g. object Process. So the column stores for example string of {"ProcessId":904,"ProcessLength":1000}. To fetch this data from db I create collection of table's records: var items = (from l in db.JDE_Logs
join u in db.JDE_Users on l.UserId equals u.UserId
join t in db.JDE_Tenants on l.TenantId equals t.TenantId
where l.TenantId == tenants.FirstOrDefault().TenantId && l.Timestamp >= dFrom && l.Timestamp <= dTo
orderby l.Timestamp descending
select new //ExtLog
{
LogId = l.LogId,
TimeStamp = l.Timestamp,
TenantId = t.TenantId,
TenantName = t.TenantName,
UserId = l.UserId,
UserName = u.Name + " " + u.Surname,
Description = l.Description,
OldValue = l.OldValue,
NewValue = l.NewValue
});. Then I query it to find matching rows for given ProcessId number e.g. query = "#NewValue.Contains(\"904,)\")";
items = items.Where(query);
This should fetch back all records where NewValue column contains the query string, but this doesn't work. It compiles and 'works' but no data are fetched or fetched are only those records where 904 appears later in the string. Sounds stupid but this is what it is.
What should the query string look like to fetch all records containing "ProcessId":904?

Speeding up a linq query with 40,000 rows

In my service, first I generate 40,000 possible combinations of home and host countries, like so (clientLocations contains 200 records, so 200 x 200 is 40,000):
foreach (var homeLocation in clientLocations)
{
foreach (var hostLocation in clientLocations)
{
allLocationCombinations.Add(new AirShipmentRate
{
HomeCountryId = homeLocation.CountryId,
HomeCountry = homeLocation.CountryName,
HostCountryId = hostLocation.CountryId,
HostCountry = hostLocation.CountryName,
HomeLocationId = homeLocation.LocationId,
HomeLocation = homeLocation.LocationName,
HostLocationId = hostLocation.LocationId,
HostLocation = hostLocation.LocationName,
});
}
}
Then, I run the following query to find existing rates for the locations above, but also include empty the missing rates; resulting in a complete recordset of 40,000 rows.
var allLocationRates = (from l in allLocationCombinations
join r in Db.PaymentRates_AirShipment
on new { home = l.HomeLocationId, host = l.HostLocationId }
equals new { home = r.HomeLocationId, host = (Guid?)r.HostLocationId }
into matches
from rate in matches.DefaultIfEmpty(new PaymentRates_AirShipment
{
Id = Guid.NewGuid()
})
select new AirShipmentRate
{
Id = rate.Id,
HomeCountry = l.HomeCountry,
HomeCountryId = l.HomeCountryId,
HomeLocation = l.HomeLocation,
HomeLocationId = l.HomeLocationId,
HostCountry = l.HostCountry,
HostCountryId = l.HostCountryId,
HostLocation = l.HostLocation,
HostLocationId = l.HostLocationId,
AssigneeAirShipmentPlusInsurance = rate.AssigneeAirShipmentPlusInsurance,
DependentAirShipmentPlusInsurance = rate.DependentAirShipmentPlusInsurance,
SmallContainerPlusInsurance = rate.SmallContainerPlusInsurance,
LargeContainerPlusInsurance = rate.LargeContainerPlusInsurance,
CurrencyId = rate.RateCurrencyId
});
I have tried using .AsEnumerable() and .AsNoTracking() and that has sped things up quite a bit. The following code shaves several seconds off of my query:
var allLocationRates = (from l in allLocationCombinations.AsEnumerable()
join r in Db.PaymentRates_AirShipment.AsNoTracking()
But, I am wondering: How can I speed this up even more?
Edit: Can't replicate foreach functionality in linq.
allLocationCombinations = (from homeLocation in clientLocations
from hostLocation in clientLocations
select new AirShipmentRate
{
HomeCountryId = homeLocation.CountryId,
HomeCountry = homeLocation.CountryName,
HostCountryId = hostLocation.CountryId,
HostCountry = hostLocation.CountryName,
HomeLocationId = homeLocation.LocationId,
HomeLocation = homeLocation.LocationName,
HostLocationId = hostLocation.LocationId,
HostLocation = hostLocation.LocationName
});
I get an error on from hostLocation in clientLocations which says "cannot convert type IEnumerable to Generic.List."
The fastest way to query a database is to use the power of the database engine itself.
While Linq is a fantastic technology to use, it still generates a select statement out of the Linq query, and runs this query against the database.
Your best bet is to create a database View, or a stored procedure.
Views and stored procedures can easily be integrated into Linq.
Material Views ( in MS SQL ) can further speed up execution, and missing indexes are by far the most effective tool in speeding up database queries.
How can I speed this up even more?
Optimizing is a bitch.
Your code looks fine to me. Make sure to set the index on your DB schema where it's appropriate. And as already mentioned: Run your Linq against SQL to get a better idea of the performance.
Well, but how to improve performance anyway?
You may want to have a glance at the following link:
10 tips to improve LINQ to SQL Performance
To me, probably the most important points listed (in the link above):
Retrieve Only the Number of Records You Need
Turn off ObjectTrackingEnabled Property of Data Context If Not
Necessary
Filter Data Down to What You Need Using DataLoadOptions.AssociateWith
Use compiled queries when it's needed (please be careful with that one...)

Intuit Quickbooks Online API - How to get purchases

I'm using Intuit's .NET SDK for QBO, and am attempting to get a list of purchases from my qbo account. Here's my C# code...
var qboCashPurchaseQuery = new Intuit.Ipp.Data.Qbo.CashPurchaseQuery();
qboCashPurchaseQuery.PageNumber = 1;
qboCashPurchaseQuery.ResultsPerPage = 100;
var results = qboCashPurchaseQuery.ExecuteQuery<Intuit.Ipp.Data.Qbo.CashPurchase(context).ToList();
grdQuickBooksCustomers.DataSource = results;
I get a table with the number of records matching the number of purchases I expect, but the actual data returned is not what I need.
This is the columns and the first row of data I get back: (sorry for the formatting)
SyncToken Synchronized IdsType
0 Intuit.Ipp.Data.Qbo
This bit of code returns the same kind of weird data for some other functions such as InvoiceQuery. What am I doing wrong here to get this data? How might I actually return the detailed purchase data I need?
string q = "Select * from Purchase Where PaymentType='Cash' STARTPOSITION 1 MAXRESULTS 100";
dynamic Purchaselist = purchaseQueryService.ExecuteIdsQuery(q);
CashPurchase cashpurchase = new CashPurchase();
foreach (CashPurchase oCash in Purchaselist) {
//do something
}
var purchase = new Purchase();
var purchases = ds.FindAll(purchase, 0, 500);
That's how we query our datasets. You have to repeat the query if you've got more than 500 items.

Search values only from first element in linq c#.net

I have the problem in where condition please check this
<Uni_Details Uni_ID="U001" User_Mode="New">
<Uni_Name>
<Full_Name>Asian</Full_Name>
<Short_Name />
</Uni_Name>
<Asc_Uni>
<Asc_Details Asc_Name="Stafford">
<Asc_Add>fsfadfsdfsdfsdf</Asc_Add>
<Asc_Tel>+44 34234234234</Asc_Tel>
<Asc_Country>United Kingdom</Asc_Country>
<Asc_Web>www.ac.lk</Asc_Web>
</Asc_Details>
</Asc_Uni>
<Branch>
<Branch_Details Branch_Name="Head Office">
<Branch_Add>dasdasdadsd</Branch_Add>
<Branch_City>Colombo</Branch_City>
<Branch_Country>Sri Lanka</Branch_Country>
<Branch_Tel>+94 342432423</Branch_Tel>
</Branch_Details>
<Branch_Details Branch_Name="Access Tower">
<Branch_Add>dfgdfgdfgdf</Branch_Add>
<Branch_City>Colombo</Branch_City>
<Branch_Country>Sri Lanka</Branch_Country>
<Branch_Tel>+94 342432453</Branch_Tel>
</Branch_Details>
</Branch>
<Uni_EMail>info#apiit.lk</Uni_EMail>
<Uni_Web>www.apiit.lk</Uni_Web>
<Course_Data>
<Course_Details Course_ID="U001C001">
<Course_Name>Computer Course</Course_Name>
<Course_Qual>Pass O/L</Course_Qual>
<Course_Dur>3 Months</Course_Dur>
<Course_Content>
<Course_Conent_List>C#.net</Course_Conent_List>
<Course_Conent_List>VB.Net</Course_Conent_List>
<Course_Conent_List>Design Practices</Course_Conent_List>
</Course_Content>
<Course_Fee>
<Fee_Amount Amount_Currency="SL Rs.">5000.00</Fee_Amount>
<Fee_Comment>Onwards</Fee_Comment>
</Course_Fee>
<Course_Desc>Learn Basic Programming practices</Course_Desc>
<Course_Next>Next October</Course_Next>
<Category_List>
<Cat_ID>2</Cat_ID>
<Cat_ID>1</Cat_ID>
</Category_List>
</Course_Details>
</Course_Data>
</Uni_Details>
<Uni_Details Uni_ID="U002" User_Mode="New">
<Uni_Name>
<Full_Name>American College</Full_Name>
<Short_Name>AC</Short_Name>
</Uni_Name>
<Asc_Uni>
<Asc_Details Asc_Name="American College USA">
<Asc_Add>fasdfsdfsdfsdsdfs</Asc_Add>
<Asc_Tel>+94 112 230623</Asc_Tel>
<Asc_Country>United States</Asc_Country>
<Asc_Web>www.ac.lk</Asc_Web>
</Asc_Details>
</Asc_Uni>
<Branch>
<Branch_Details Branch_Name="Head Office">
<Branch_Add>FFSDFASDFSDF</Branch_Add>
<Branch_City>Colombo</Branch_City>
<Branch_Country>Sri Lanka</Branch_Country>
<Branch_Tel>+94 112 230623</Branch_Tel>
</Branch_Details>
</Branch>
<Uni_EMail>info#ac.lk</Uni_EMail>
<Uni_Web>www.ac.lk</Uni_Web>
<Course_Data>
<Course_Details Course_ID="U002C0001">
<Course_Name>Computer Course</Course_Name>
<Course_Qual>O/L Pass</Course_Qual>
<Course_Dur>3 Months</Course_Dur>
<Course_Content>
<Course_Conent_List>C#.net</Course_Conent_List>
<Course_Conent_List>VB.Net</Course_Conent_List>
<Course_Conent_List>Design Practices</Course_Conent_List>
</Course_Content>
<Course_Fee>
<Fee_Amount Amount_Currency="SL Rs.">5000</Fee_Amount>
<Fee_Comment></Fee_Comment>
</Course_Fee>
<Course_Desc>Basics</Course_Desc>
<Course_Next>Next October</Course_Next>
<Category_List>
<Cat_ID>1</Cat_ID>
</Category_List>
</Course_Details>
<Course_Details Course_ID="U002C0002">
<Course_Name>Accounting Course</Course_Name>
<Course_Qual>O/L Pass</Course_Qual>
<Course_Dur>6 Months</Course_Dur>
<Course_Content>
<Course_Conent_List>Accounts Basics</Course_Conent_List>
<Course_Conent_List>Business Studies</Course_Conent_List>
<Course_Conent_List>Acc Pack</Course_Conent_List>
</Course_Content>
<Course_Fee>
<Fee_Amount Amount_Currency="SL Rs.">10000</Fee_Amount>
<Fee_Comment></Fee_Comment>
</Course_Fee>
<Course_Desc>Basic Accounting</Course_Desc>
<Course_Next>Next January</Course_Next>
<Category_List>
<Cat_ID>3</Cat_ID>
<Cat_ID>2</Cat_ID>
</Category_List>
</Course_Details>
</Course_Data>
</Uni_Details>
this is my XML file I need to retrieve all data which cat_id is 1
var data = (from cats in data_file.Elements("Uni_Data").Elements("Uni_Details")
where cats.Element("Course_Data").Element("Course_Details").Element("Category_List").Element("Cat_ID").Value == cat_id.ToString()
select new
{
uni_name = cats.Element("Uni_Name").Element("Full_Name").Value.ToString(),
uni_short = cats.Element("Uni_Name").Element("Short_Name").Value.ToString(),
price = cats.Element("Course_Data").Element("Course_Details").Element("Course_Fee").Element("Fee_Amount").Value.ToString()
});
however this works if I have cat_id 1 as my first element if its in second place it won't listed so plz help me with this
The problem is with the way the end of your where clause is setup: Element("Cat_ID").Value == cat_id.ToString().
Specifically, the Element("Cat_ID") part will check the first child "Cat_ID" element. So if Cat_ID 1 is the second item, it won't be found. Instead, you need to check all child elements for a match.
var data = (from cats in data_file.Elements("Uni_Data").Elements("Uni_Details")
let catId = cats.Element("Course_Data").Element("Course_Details").Element("Category_List").Elements("Cat_ID").FirstOrDefault(c => c.Value == cat_id.ToString())
where catId != null
select new
{
uni_name = cats.Element("Uni_Name").Element("Full_Name").Value.ToString(),
uni_short = cats.Element("Uni_Name").Element("Short_Name").Value.ToString(),
price = cats.Element("Course_Data").Element("Course_Details").Element("Course_Fee").Element("Fee_Amount").Value.ToString()
});
The query uses a let clause to store the result of the FirstOrDefault call, which uses the predicate to match the criteria. Next, if it isn't null then the rest of the query works as before. If it's null it means no match was found.
That said, your query has a lot of repeated elements. It also uses .Value.ToString() in a few places, which is redundant since the Value property already returns a string. I would clean up the query as follows:
var data = from cats in data_file.Elements("Uni_Data").Elements("Uni_Details")
let uniName = cats.Element("Uni_Name")
let details = cats.Element("Course_Data").Element("Course_Details")
let catId = details.Element("Category_List").Elements("Cat_ID").FirstOrDefault(c => c.Value == cat_id.ToString())
where catId != null
select new
{
uni_name = uniName.Element("Full_Name").Value,
uni_short = uniName.Element("Short_Name").Value,
price = details.Element("Course_Fee").Element("Fee_Amount").Value
};

Why am I getting index out of bounds error from database

I know what index out of bounds is all about. When I debug I see why as well. basically what is happening is I do a filter on my database to look for records that are potential/pending. I then gather a array of those numbers send them off to another server to check to see if those numbers have been upgraded to a sale. If it has been upgraded to a sale the server responds back with the new Sales Order ID and my old Pending Sales Order ID (SourceID). I then do a for loop on that list to filter it down that specific SourceID and update the SourceID to be the Sales Order ID and change a couple of other values. Problem is is that when I use that filter on the very first one it throws a index out of bounds error. I check the results returned by the filter and it says 0. Which i find kind of strange because I took the sales order number from the list so it should be there. So i dont know what the deal is. Here is the code in question that throws the error. And it doesn't do it all the time. Like I just ran the code this morning and it didn't throw the error. But last night it did before I went home.
filter.RowFilter = string.Format("Stage = '{0}'", Potential.PotentialSale);
if (filter.Count > 0)
{
var Soids = new int[filter.Count];
Console.Write("Searching for Soids - (");
for (int i = 0; i < filter.Count; i++)
{
Console.Write(filter[i][1].ToString() + ",");
Soids[i] = (int)filter[i][1];
}
Console.WriteLine(")");
var pendingRecords = Server.GetSoldRecords(Soids);
var updateRecords = new NameValueCollection();
for (int i = 0; i < pendingRecords.Length; i++)
{
filter.RowFilter = "Soid = " + pendingRecords[i][1];
filter[0].Row["Soid"] = pendingRecords[i][0];
filter[0].Row["SourceId"] = pendingRecords[i][1];
filter[0].Row["Stage"] = Potential.ClosedWon;
var potentialXML = Potential.GetUpdatePotentialXML(filter[0].Row["Soid"].ToString(), filter[0].Row["Stage"].ToString());
updateRecords.Add(filter[0].Row["ZohoID"].ToString(), potentialXML);
}
if i'm counting right line 17 is the error where the error is thrown. pendingRecords is a object[][] array. pendingRecords[i] is the individual records. pendingRecords[i][0] is the new Sales OrderID (SOID) and pendingRecords[i][1] is the old SOID (now the SourceID)
Any help on this one? is it because i'm changing the SOID to the new SOID, and the filter auto updates itself? I just don't know
Well I ended up changing how it worked all together and it actually sorts it a bit nicer now. The code i am about to post has a bunch of hard coded numbers due to the structure of my table that is returned. Sorry about that. I have learned since then to not do that, but i am working on a different project now and will change that when I have to change the program. But here is the solution.
var potentials = Server.GetNewPotentials(); //loads all records from server
for (int i = 0; i < potentials.Length; i++)
{
var filter = AllPotentials.DefaultView;
var result1 = CheckSoidOrSource(potentials[i].Soid, true);
var result2 = CheckSoidOrSource(potentials[i].SourceID,false) ;
//This potential can't be found at all so let's add it to our table
if (result1+result2==0)
{
Logger.WriteLine("Found new record. Adding it to DataTable and sending it to Zoho");
AllPotentials.Add(potentials[i]);
filter.RowFilter = string.Format("Soid = '{0}'", potentials[i].SourceID);
var index = AllPotentials.Rows.IndexOf(filter[0].Row);
ZohoPoster posterInsert = new ZohoPoster(Zoho.Fields.Potentials, Zoho.Calls.insertRecords);
AllPotentials.Rows[index]["ZohoID"] = posterInsert.PostNewPotentialRecord(3, filter[0].Row);
}
//This potential is not found, but has a SourceId that matches a Soid of another record.
if (result1==0 && result2 == 1)
{
Logger.WriteLine("Found a record that needs to be updated on Zoho");
ZohoPoster posterUpdate = new ZohoPoster(Zoho.Fields.Potentials, Zoho.Calls.updateRecords);
filter.RowFilter = string.Format("Soid = '{0}'", potentials[i].SourceID);
var index = AllPotentials.Rows.IndexOf(filter[0].Row);
AllPotentials.Rows[index]["Soid"] = potentials[i].Soid;
AllPotentials.Rows[index]["SourceId"] = potentials[i].SourceID;
AllPotentials.Rows[index]["PotentialStage"] = potentials[i].PotentialStage;
AllPotentials.Rows[index]["UpdateRecord"] = true;
AllPotentials.Rows[index]["Amount"] = potentials[i].Amount;
AllPotentials.Rows[index]["ZohoID"] = posterUpdate.UpdatePotentialRecord(3, filter[0].Row);
}
}
AllPotentials.AcceptChanges();
}
private int CheckSoidOrSource(string Soid, bool checkSource)
{
var filter = AllPotentials.DefaultView;
if (checkSource)
filter.RowFilter = string.Format("Soid = '{0}' OR SourceId = '{1}'",Soid, Soid);
else
filter.RowFilter = string.Format("Soid = '{0}'", Soid);
return filter.Count;
}
basically what is happening is that i noticed something about my data when I filter it this way. The two results would only return the following results (0,0) (0,1) and (1,0) (0,0) means that the record doesn't exist at all in this table so I need to add it. (1,0) means that the Sales Order ID (Soid) matches another Soid in the table so it already exists. Lastly (0,1) means that the Soid doesn't exist in this table but i found a record that has the Soid as it's source...which to me means that the one that had it as a source has been upgraded from a potential to a sale, which in turn means i have to update the record and Zoho. This worked out to much less work for me because now I don't have to search for won and lost records, i only have to search for lost records. less code same results is always a good thing :)

Categories

Resources