Using Linq, I get this: There is already an open DataReader associated with this Command which must be closed first - asp.net

Here's what I'm trying to do:
IEnumerable<OfficeView> allOffices = GetAllOffices(); //this method also uses some linq query
foreach (var office in allOffices)
{
officeSales.Add(
new Tuple<int, decimal>(office.Id, GetSaleAmount(office.Id, someParams)));
}
public decimal GetAgentSaleAmount(int officeRef, someTypes someParams)
{
var q = ObjectQuery.Where
(i => i.officeId == officeRef && i.someOtherStuff == someParams)
.ToList();
return q.Sum(i => i.NetPrice);
}
I can't set MultipleActiveResultSets = true. Instead, as suggested here, I tried to do .ToList() before doing the summation, but got the same error. (and even if I wouldn't get the error, I think it would cause heavy load to fetch everything just to get the summation of one field)
I will be super thankful for any suggestion to solve this problem!
Update: The problem was all about GetAllOffices(), which returned IEnumerable (which leaves the DataReader open). I changed the first line as below and it worked. Thanks a lot guys :)
IEnumerable<OfficeView> allOffices = GetAllOffices().ToList();

Error said that reader is already opened, that means that you have run some query before which needs to close.
Write .ToList() to that linq query and do same for other queries too.

I think you are trying to do both adding and querying at the same time.You need to finish adding "Sale" object to "Sales" collection before trying to calculate the sales value.
In other words, you cannot query until the transaction is committed. Hope that helps.

Related

SQL Lite Xamarin : Query

I'm newbie in SQLite.
I would like to query my SQLite database to get multiple rows.
When I add a new item in my local database I call this method Add:
public bool Add<T>(string key, T value)
{
return this.Insert(new SQliteCacheTable(key, this.GetBytes(value))) == 1;
}
_simpleCache.Add("favorite_1", data1);
_simpleCache.Add("favorite_2", data2);
_simpleCache.Add("favorite_3", data2);
Then,
I would like to retrieve from local database all entries where key starts with "favorite_"
to returns all objects in the database which are "favorite" objects.
I'm experienced in Linq, and I would like to do something like this:
IEnumerable<Element> = repository.Find((element) => element.Key.StartWith("favorite_"))
In the SQLiteConnection class there is a method like this:
SQLite.Net.SQLiteConnection.Find<T>(System.Linq.Expressions.Expression<System.Func<T,bool>>)
But I would like the same with in returns a collection IEnumerable<T>.
Can you help me please?
Thank you.
Jool
You have to build your query on the table itself, not the connection:
Assuming:
SQLiteConnection repository;
Then the code would look like:
var favorites = repository.Table<SQliteCacheTable>().Where(item => item.StartsWith("favorite_"));
The favorites variable is of type TableQuery<SQliteCacheTable> though, so it does not yet contain your data. The execution of the actual SQL query will be deferred until you try to access the results (by enumerating with foreach or converting to a list with ToList, for example).
To actually observe what's going on on the database, you can turn on tracing in sqlite-net, by setting repository.Trace = true on your SQLiteConnection object.
Finally, it's worth mentioning that you can also use the C# query syntax on TableQuery<T> objects, if your comfortable with it. So your query could become:
var favorites = from item in repository.Table<SQliteCacheTable>()
where item.StartsWith("favorite_")
select item;

entity framework, how to use object query with a WHERE, AND to retrieve entity record

I am trying to add and AND condition to my entity framework where clause, but the way I am doing it is not working. Can anyone show me how to do this the correct way please? Before adding the AND condition, the code worked fine.
Dim myRecipeStepsHistory = myContext.RefineRecipeStep.Where("it.Recipe_Id=" & strRecipeId And "it.IngredientItemNumber=" & strIngredientNumber).FirstOrDefault()
The error I get reads as:
Conversion from string "it.Recipe_Id=11" to type 'Long' is not valid.
Thank you very much.
I would try to use the built in linq if you can. It will check your values at compile time for you and you won't get nasty surprises at run time. You can use magic-strings of course but why not use one of the best features of of an ORM? Imagine updating a tables field type, the compiler will automatically let you know every place you need to update your code. Instead of having forgetting about one and then having it crash here and there.
If you're querying a single table, often it's easier to put the 'wheres' inside the FirstOrDefault();
Dim myRecipeStepsHistory =
myContext.RefineRecipeStep
.FirstOrDefault(x => x.Recipe_Id.Equals(strRecipeId) &&
x.IngredientItemNumber == strIngredientNumber);
if(myRecipeStepHistory != null)
{
//
}
You may have to cast your values so it matches the correct data type for Recipe_Id and IngredientItemNumber.
may be a space is missing and/or a " is missplaced:
Dim myRecipeStepsHistory = myContext.RefineRecipeStep.Where("it.Recipe_Id=" & strRecipeId.ToString() & " And it.IngredientItemNumber=" & strIngredientNumber.ToString()).FirstOrDefault()
Presumably, if you are using EF, your model already knows about RefineRecipeStep, and thus you shouldn't be writing sql in place like that?
Thus what you want becomes something more like:
Dim myRecipeStepsHistory = myContext.RefineRecipeStep
.Where((it) => it.Recipe_Id.Equals(recipeId))
.Where((it) => it.IngredientItemNumber.Equals(ingredientNumber))
.FirstOrDefault()
or possibly:
Dim myRecipeStepsHistory = myContext.RefineRecipeStep
.Where((it) => it.Recipe.Id.Equals(recipeId))
.Where((it) => it.IngredientItemNumber.Equals(ingredientNumber))
.FirstOrDefault()
if recipe is a known relationship...

Binding database data to a dropdownlist

I have been trying for a long time to fix the bugs I'm encountering with my dropdownlists in my project. I'm getting data this with at the moment and it's working fine:
using (InfoEntities ie = new InfoEntities())
{
var sqlddl = (from query in ie.Table_Customers
from q in ie.Accounting_PriceType
where query.TypeID == 1 && q.ID == 1
orderby query.Customers
select query).Distinct().ToList();
DropDownListCust.DataTextField = "Customers";
DropDownListCust.DataValueField = "ID";
DropDownListCust.DataSource = sqlddl;
DropDownListCust.DataBind();
}
Now when the user saves the data and opens the website again I need the saved value that was chosen on the dropdownlist earlier retreived. This also works fine but the problem is I'm getting duplicates. Anyways I'm doing it like this and I'm pretty sure I'm doing it wrong:
On the page load i load my dropdownlist to get all the items plus the following to get the saved value:
DropDownListCust.SelectedItem.Text = sql.Customers;
This makes my DDL very buggy, some items dissapear and also sometimes dupicated values. Can anyone please help? I'm using LINQ but I can use some other methods as long as it's fixed.
Cheers
I solved my problem like this:
DropDownList1.ClearSelection();
DropDownList1.Items.FindByText(sql.Customer).Selected = true;

Cannot implicitly convert type to List<string>

Afternoon,
I am getting the following error, and cant work out why... Can some one please take a look and let me know where i am going wrong.
Cannot implicitly convert type 'System.Collections.Generic.List' to 'System.Collections.Generic.List'
below is what i am trying to use, to get a list back so i can use it with Amazon. I have tried to remove the .ToList() bit but nothing seems to work. I am calling an MS SQL view "GetASINForUpdateLowPrices" which returns a list back of product ASIN's
List<string> prodASINs = dc.GetASINForUpdateLowPrices.ToList();
SQL for the view i am using, this may help a little bit more.
SELECT asin
FROM dbo.aboProducts
WHERE (asin NOT IN
(SELECT aboProducts_1.asin
FROM dbo.aboProducts AS aboProducts_1 INNER JOIN
dbo.LowestPrices ON aboProducts_1.asin = dbo.LowestPrices.productAsin
WHERE (dbo.LowestPrices.priceDate >= DATEADD(day, - 1, GETDATE()))))
What data type is a single ASIN?
Probably your GetASINForUpdateLowPrices is not an IEnumerable<string>. Try this to confirm:
List<string> prodASINs = dc.GetASINForUpdateLowPrices
.Select(e => e.ToString())
.ToList();
When you call your GetASINForUpdateLowPrices, it wont directly return List<string> even if there is only one field in your view. Try the following approach:
List<string> prodASINs = dc.GetASINForUpdateLowPrices
.Select(item => item.AsinFieldName)
.ToList();
Visual Studio IntelliSense should suggest you the property name after typing item.. If the property is not string try to add .ToString() at the end of the property name.
Edit: After your comment, it seems like you need to use it as .Select(item => item.asin.ToString()).
Just use var.
var prodASINs = dc.GetASINForUpdateLowPrices.ToList();
Are you sure that GetASINForUpdateLowPrices.ToList() creates a List of Strings? My best estimation is that it is a generic list of a different type.
To figure out what is going on - Change List<string> prodASINS to be Object obj. Then set a breakpoint to see what List type is actually generated by your ToList() code by checking out the object using the debugger. You can then update your code to move the values into a list of the appropriate type.
You might have to cast the right side of the assignor like this to ultimately get the job done (replacing string with another type if necessary) - List<string> prodASINs =(List<string>)dc.GetASINForUpdateLowPrices.ToList()

Why won't this sequence of entities sort in the GridView after binding?

This sequence I created works well in LINQPad
IQueryable<AccessRequest> filteredRows1;
// retrieve the last record of each request in its request history
filteredRows1 = from req in AccessRequestSet
group req by req.TaskReferenceId
into g
let topReq = g.OrderByDescending(r => r.UpdateDate).FirstOrDefault()
select topReq;
IQueryable<AccessRequest> filteredRows =
filteredRows1.Where(o => o.Status == "Requested");
I want to then sort these entities by the field, RequestedReleaseTime.
filteredRows.OrderBy(p => p.RequestedReleaseTime);
Again I'm grouping by one DateTime successfully, and then sorting by another DateTime successfully, confirmed in LINQPad. I then add this as a DataSource and bind to my GridView:
gvRequests.DataSourceID = string.Empty;
gvRequests.DataSource = filteredRows;
gvRequests.DataBind();
I have even set AllowSorting="true" and added this line to Sort.
gvRequests.Sort("RequestedReleaseTime", SortDirection.Ascending);
I have tried this last line before and after the DataBind to no avail. What is wrong with this approach? Should I be doing any of this within the OnSorted or OnSorting events? Note: I tried that and got StackOverflowException, which reminded me that I should be asking you guys. Thanks millions for any direction or help I receive.
Calling OrderBy doesn't actually modify the original query, but instead returns a new query based on the original, which you need to pick up:
var filteredRowsOrdered = filteredRows.OrderBy(p => p.RequestedReleaseTime);
I believe the gridview's "sort" is intended to work with something like an ObjectDataSource, which knows to call a method to retrieve the data and pass a sort string into that method. Unfortunately, this doesn't work very well with Entity Framework. We've figured out some tricks to make our data-access classes figure out how to convert a sort expression into a q = q.OrderBy(...) statement. But it can be complicated.

Resources