I am using link to sql, I have a connected set of objects.
I start out and do a linq statement like this
Dim L= from II in context.InventoryItems select II
Dim L2 = L.tolist
The second line was so that I could narrow down where the problem was occuring. When the second line is hit I get an error "The EntitySet is already loaded and the source cannot be changed"
Any ideas what might be causing this?
Omer's comment brings up a very good point: is this DataContext being re-used from a previous operation? If so, you may want to check out Dino Esposito's blog post regarding lifetime of the DataContext to make sure you're not keeping it around too long.
That error sounds like maybe you have already loaded data from the InventoryItems table using that DataContext and possibly made some changes to entities bound to the DataContext that you have not yet submitted. If you try your code with a brand new DataContext without specifying any special DataLoadOptions it should work.
For anyone interested, be careful what you do in the constructor, I was initializing some stuff in the constructor that I shouldn't have been and it caused an error on loading from the datacontext.
Related
I've been developing an app which uses strongly typed datasets and stored procedures. I've just graduated and this was the method that was sold to us as the way to go. I'm starting to have severe doubts.
My client has advised me that he might change from SQL Server to MySQL. From what I've read it might be better to not use stored procedures as migrating could become more difficult. So anyhow I've just implemented a new table adapter query using the wizard and selected Use SQL Statements rather than Create new stored procedure.
My call to the query
Intranet.administratorsDataTable dt = taAdministrators.GetAdministrators();
now generates this error:
executereader requires an open and available connection. the
connection's current state is closed
I have no idea why this auto generated code doesn't have a connection and I'm hungover and in no shape to deal with this. I decided to just go back to the SP's for the moment so I can get some work done. This error is still being thrown (same table adapter, same method name but reconfigured to use a SP). All of my other DB calls work fine.
I'm assuming the generated SQL code is still floating around somewhere even though I changed the adapter to use SP's. Can someone tell me where it is so I can delete it?
On another note I'm really starting to think that using SqlConnection and SqlCommand manually is a much better option, as using these query 'Tools' are just way to much trouble when it comes to flexibility such as modifying database tables etc. Can any of you more experienced people tell me if that's correct or do you advocate using table adapters?
*Edit
it also throws these:
Invalid operation. The connection is closed.
and
There is already an open DataReader associated with this Command which must be closed first.
The solution was to go to the query properties in the tableAdapter and manually change the "Command Type" to StoredProcedure.
highlight the query > go to properties window > change the command type
Seem this didn't (or doesn't) get auto updated when I reconfigure the query.
if you provide some code, it would be better.
I think, you need to open the the connection.
SqlCommand Cmd= new SqlCommand();
Cmd.Open();
// then u can use Cmd.ExecuteReader();
I have recently started to use Nhibernate and i am quite happy with it until i needed to BIND to ASP.NET controls. I was having major issues binding a gridview to a collection of Products (IList). In the end i was forced to right a small routine to convert my IList to a DataTable. Once it was in datatable it worked flawlessy.
Now has come the time to bind a standard Dropdownbox to 1 field of a collection (IList) of Products but it appears i am having issues again.
So this has brought me to the conclusion that i must be doing something wrong?
I can't believe that it isn't possible to BIND ASP.NET controls to a collection (IList) of a class (in my case products) that is returned from NHibernate.
I would really appreciate any feedback anyone has on the situation... I am at a loss
Thank you
The problem is not that you can't bind, because you can. Generally issues like this come about when you're binding at the wrong time.
NHibernate supports laziness. So if your query is lazy, and properties on the returned objects are lazy, then the values won't be pulled from the database until the items and properties are referenced. If you bind these to controls in the UI, then the values won't be extracted until the page gets rendered.
At this point there is a good chance that you have already closed your database connection.
The simple solution is to make sure that the data you're binding to is not lazily loaded.
Create a List<T> or BindingList<T> object and pass the IList object from the query into the constructor. If the IList object is not a generic list, you can use LINQ, ilistObject.Cast<T>().ToList().
I have built my first MVC solution and used the repository pattern for retrieving/inserting/updating my database.
I am now in the process of refactoring and I've noticed that a lot of (in fact all) the methods within my repository are hitting the database everytime. This seems overkill and what I'd ideally like is to do is 'cache' the main data object e.g. 'GetAllAdverts' from the database and to then query against this cached object for things like 'FindAdvert(id), AddAdvert(), DeleteAdvert() etc..'
I'd also need to consider updating/deleting/adding records to this cache object and the database.
What is the best apporoach for something like this?
My knowledge of this type of things is minimal and really looking for advice/guidance/tutorial to point me in the right direction.
Thanks in advance.
This just hit my radar, and I assume you have already solved the issue by now. But if not, I would look into Pre-Compiled LINQ Queries. Something like this:
private static Func<SomeDataContext, int, PersonDto> _getPersonByIdQuery =
CompiledQuery.Compile<SomeDataContext, int, PersonDto>(
(dataContext, personId) =>
dataContext.PersonDtos.where(c => c.PersonId == personId).FirstOrDefault()
);
Put something like that inside of your datacontext, then add an internal method in there to call it call it. Your retriever/saver will then call the internal method. Does that make sense? I can post more code if necessary..
Best of luck,
Justin
Afternoon all
This is driving me nuts.
For no apparent reason (of course there must be one), my web project will no longer generate LINQ to SQL classes/data contexts!!!
I am going about the usual routine of right clicking the project, adding new item, selected LINQ to SQL classes, then dragging over a table from Server Explorer, saving and build but no...the bloody thing won't appear!!!
Does anyone know why this might be happening/what have I done wrong?
Figured it out.
Basically, NEVER rename any items.
I had previously been using OnlineReporting in one item, the name space when linq creates the classes was using this as it's namespace.
However, I then later changed this to Reporting but when the linq to sql generation occurred, it was still using the 'old' namespace.
I went into the designer.cs file, amended the name space to match the new format and it worked.
I have a problem with Gridview sorting that is similar to others but I'm binding to a collection object as opposed to a data table.
The existing business rules and data access layers of an application follow the pattern of having an object and, if you need a collection of objects of that type, to have another class inheriting CollectionBase and implementing IBindingList.
For desktop applications, it was easy to databind a gridview to one of these objects and there weren't any problems with turning on column sorting. Everything was 'in state' in the desktop app's presentation layer.
Now that code is being moved to a new web application (ASP.NET 2.0, VB codebehind pages).
I've played around with what I had to do to only have certain columns of the collection show up in the gridview and the gridview looked pretty good. When I turned on 'allow sorting', that's when the problems showed up.
I'm getting the error about not having a .Sorting method, etc. In researching this, I found all sorts of solutions that were easily implemented with dataviews if my source was a data table. But it's not - it's a collection. I tried to "cheap shot" a datasource by converting the collection to an XML memory stream and them trying to .ReadXML back into a dataset but that didn't work [Root element is missing error was as far as I got in the dataset.ReadXml(ioTemp) where ioTemp was the System.IO.MemoryStream used in the xml serializer].
Because of the old desktop apps, I've never had to worry about sorting a collection since the gridview handled it once it was loaded. In fact, it's a 'standard' that the collection's .SortProperty, .SortDirection and .ApplySort all through NotSupportedExceptions (I inherited this code from programmers long gone).
Is there an easy way to convert the collection to a data table or a way to sort the collection without having to go back to the database each time? Object Data Sources won't work becuase of the intricate rules in how the objects are built - the wizards in VS2005 just can't handle what we need to do (grabbing data from several tables conditionally to make an object).
Thanks in advance.
Have you considered client side sorting instead?
I have used the jquery tablesorter plugin in the past with ASP Gridviews.
http://tablesorter.com/
I had a similar issue and i needed to implement IComparable on the objects. Basically to sort a collection of objects you need a way to distinguish their order. The IComparable interface has one method called Compare which allows the .Net framework to work out the order of the objects when you sort them. You need to implement this method yourself to get the sort method to work.
Google results
You don't mention the error message so i cant be sure if this is the case, can you post the error?
EDIT :
In regards to your comment; you can implement multi column sorting, it just requires more work. You can specify the fields to sort the collection by and then use this information within the CompareTo Method.
Have a look at this
Given that you apparently are populating the grid with a collection of your own objects, this sounds like a perfect job for Linq for Objects. With just a little elbow grease you can achieve what is effectively an SQL Select statement against your collection. Very cool stuff.
http://www.hookedonlinq.com/LINQtoObjects5MinuteOverview.ashx
Also, do you really just want to sort the data in the grid? If so, then'd definitely pursue using Linq against your objects. However, rarely does sorting the contents of the grid really answer the problem ("sorting the grid" usually translates into changing the access path of the data used to fill the grid.) Browser apps aren't like Windows apps and don't have a full-time connection to the underlying data source to make things happen quite as magically as the DataGridView in Windows makes things seem.
You can put link buttons with an On_Click event as the header's of each column.
When the event is triggered, figure out which header was clicked on (one method per header or a commandArgument value). Once that is know, do a .orderBy or .OrderByDescending by on the collection of objects, and put the result back in as datasource of the gridview and databind on that.
In the year since I originally asked this question, I managed to get a new 'standard' implemented so that collections of business objects were now generic lists.
So now a "Collection class" that is little more than a "Inherits List(Of MyBusinessObject)" with a Sort Method that looks like this (performance wasn't an issue):
Public Overloads Sub Sort(ByVal strPropertyName As String, ByVal strDirection As String)
Dim arSortedList As New ArrayList
For Each item As MyBusinessObject In Me
arSortedList.Add(item)
Next
arSortedList.Sort(New CaseInsensitiveComparer(Of MyBusinessObject)(strPropertyName, strDirection))
For intI As Integer = 0 To arSortedList.Count - 1
Item(intI) = arSortedList(intI)
Next
End Sub
This seemed to work perfectly with the methodology used by the GridView for firing events.