I continue to receive the error that "There is already an open DataReader associated with this Command which must be closed first." when I execute following in ASP.NET MVC 4.5
foreach (var store in db.Stores)
{
var productsInStore = store.Products.ToList();
}
In my solution there a class called Store and in this particular example, I am trying to convert the Products inside each store into a new variable.
How can this be achieved?
You can force EF to load all entities immediately. To do so call ToList():
foreach (var store in db.Stores.ToList())
{
var productsInStore = store.Products.ToList();
}
Related
Workflow:
I have a winform app with two forms, in the 1st form I query a liteDB and it manipulates an IEnumerable<T> instance inside a using block with retrieved data.
IEnumerable<student> searchResult;
using(var db = new LiteDatabase(#"C:\Temp\MyData.db"))
{
var col = db.GetCollection<student>("students");
col.EnsureIndex(x => x.contact.phone);
searchResult = col.Find(x => x.contact.phone == "123456789");
}
Form2 frm2 = new Form2();
Form2.profileData = searchResult.AtElement(index);
Problem:
I then, need to send an element of searchResult<student> to 2nd form in order to show user, as you can see in the last 2 lines of above code.
But since it's inside using block, I get System.ObjectDisposedException.
Data types and exception:
studentCollection.Find():
searchResult:
Exception:
Addition:
What I already though of as possible way is:
Override and nullify existing dispose() method then call my own implemented method after I'm done; Which is basically equals to not having a using block, except that I don't have to take care of disposing other objects in above using block, but only searchResult<student>.
P.S:
I'm newbie at whole thing, appreciate the help and explanation
I'm not familliar with LiteDb, but I would assume it returns a proxy object for the database. So when the database is disposed, the proxy-object is no longer usable.
The simple method to avoid the problem is to add .ToList() after the .Find(...). This will convert the proxy-list to an actual List<T> in memory, and it can be used after the database is disposed. It is possible that the student objects inside the list are also proxies, and if that is the case this will fail.
If that is the case you either need to find some way to make the database return real, non-proxy objects, or extend the lifetime of the database to be longer than that of your form, for example
IList<student> myIList;
using(var db = new LiteDatabase(#"C:\Temp\MyData.db"))
{
var col = db.GetCollection<student>("students");
col.EnsureIndex(x => x.contact.phone);
myIList = col.Find(x => x.contact.phone == "123456789");
using(var frm2 = new Form2()){
frm2.profileData = myIList.AtElement(index);
frm2.ShowDialog(this);
}
}
Note the usage of .ShowDialog, this will block until the second form has been closed. That is not strictly necessary, but it makes it much easier to manage the lifetime of the database.
You need to access the element before exiting the using block.
using(var db = new LiteDatabase(#"C:\Temp\MyData.db"))
{
var col = db.GetCollection<student>("students");
col.EnsureIndex(x => x.contact.phone);
var searchResult = col.Find(x => x.contact.phone == "123456789");
Form2 frm2 = new Form2();
Form2.profileData = searchResult.AtElement(index);
}
I'm trying to save multiple data from the list i created and so I created a foreach loop
foreach (var jline in jobline)
{
var pjobline = new PrintJobLine();
pjobline.PrintJobId = pjguidno; // jline.PrintJobId;
pjobline.LineIndex = jline.LineIndex;
pjobline.Text = jline.Text;
pjobline.PrintOptions = jline.PrintOptions;
pjobline.ItemName = jline.ItemName;
pjobline.Quantity = jline.Quantity;
_posContext.PrintJobLines.Add(pjobline);
_posContext.SaveChanges();
}
transaction.Commit();
result = true;
The Process Finished Without any error on the code but When I check on my Database Table the Data is not saved it is empty.
I'm doing this in .Net Core C#.
I have faced same problem before, mostly due to data you are trying to save; if it not right EF core will not raise an exception. So, check fields in PrintJobLines table which is required and has no default value, data type and length
I'm using the lazy singleton pattern in C# for my data managers. The code in my manager looks like this:
private static readonly Lazy<ConditionManager> singleton =
new Lazy<ConditionManager>(() => new ConditionManager());
public static ConditionManager Instance { get { return singleton.Value; } }
Then in my code, I am trying to see if the item exists before I create it:
//see if condition exists. If it doesn't then create it.
List<Condition> conditions = ConditionManager.Instance.Select
(question.Id, ConditionType.ProjectQuestion);
Condition c;
if (conditions.Count == 0)
{
c = new Condition(question.Id, ConditionType.ProjectQuestion, ReleaseId);
c.Id = ConditionManager.Instance.Insert(c);
}
The problem is that, when I call the Insert, I get the dreaded error: "There is already an open DataReader associated with this Command which must be closed first." I have found a workaround (I have one call to the ConditionManager that both checks to see if it exists and then returns either the existing one of the newly created one), but what is the proper way to handle this? How do I close the first instance?
I have developed a WCF api which is using nHibernate. I am new to this. I have used session.update to take care of transaction. I have a for loop in which based on select condition I am updating a record ie. If A is present in tabel1 then I am updating the table else inserting a new entry.
I am getting "could not execute query." when trying to execute a select query on a table which was previously being updated by adding a new entry in the table.
What I think is, because I am using session.save(table1) and then trying select entries from that table I am getting an error. Since session.save temporarily locks the table I am not able to execute a select query on that table.
What can be the solution on this?
Update:
This the for loop I am using to check in the database for some field:
using (ITransaction tranx = session.BeginTransaction())
{
savefunction();
tranx.Commit();
}
Save function:
public void savefunction()
{
for (int i = 0; i < dictionary.Count; i++)
{
ICandidateAttachmentManager candidateAttach = new ManagerFactory().GetCandidateAttachmentManager();
CandidateAttachment attach = new CandidateAttachment();
attach = checkCV();
if(attach == null)
{
//insert new entry into table attach
session.save(attach);
}
}
}
checkCV function:
public void checkCV()
{
using (ICandidateAttachmentManager CandidateAttachmentManager = new ManagerFactory().GetCandidateAttachmentManager())
{
IList<CandidateAttachment> lstCandidateAttachment = CandidateAttachmentManager.GetByfkCandidateId(CandidateId);
if (lstCandidateAttachment.Count > 0)
{
CandidateAttachment attach = lstCandidateAttachment.Where(x => x.CandidateAttachementType.Id.Equals(FileType)).FirstOrDefault();
if (attach != null)
{
return null;
}
else
{
return "some string";
}
}
}
}
What happening here is in the for loop if say for i=2 the attach value comes to null that I am entering new entry into attach table. Then for i=3 when it enters checkCV function I get an error at this line:
IList lstCandidateAttachment =
CandidateAttachmentManager.GetByfkCandidateId(CandidateId);
I think it is because since I am using session.save and then trying to read the tabel contents I am unable to execute the query and table is locked till I commit my session. Between the beginTransaction and commit, the table associated with the object is locked. How can I achieve this? Any Ideas?
Update:
I read up on some of the post. It looks like I need to set isolation level for the transaction. But even after adding it doesn't seem to work. Here is how I tried to inplement it:
using (ITransaction tranx = session.BeginTransaction(IsolationLevel.ReadUncommitted))
{
saveDocument();
}
something I don't understand in your code is where you get your nHibernate session.
Indeed you use
new ManagerFactory().GetCandidateAttachmentManager();
and
using (ICandidateAttachmentManager CandidateAttachmentManager = new ManagerFactory().GetCandidateAttachmentManager())
so your ManagerFactory class provides you the ISession ?
then you do:
CandidateAttachment attach = new CandidateAttachment();
attach = checkCV();
but
checkCV() returns either a null or a string ?
Finally you should never do
Save()
but instead
SaveOrUpdate()
Hope that helps you resolving your issue.
Feel free to give more details
i want to compare through 2 information, one is user input and second is admin ID in database. in my project, i'm using WCF Ria. i did created one auto-generated Domain Service Class and the code to retrieve everything in tblAdmin was auto-generated. i load the data in this way ::
var context = new OrganizationContext();
var x = context.tblAdmins;
context.Load(context.GetTblAdminsQuery());
cb1.ItemsSource = x;
it can load in this way, but i cannot get the x.adminID with this. so i tried this ::
foreach (var admin in x)
{
cb1.Items.Add(admin.adminID);
}
but failed... may i know is that possible to dig through the data without foreach or is there something wrong in my code ??
Looks like the problem is that the context.Load call is asynchronous - to get the result you need to pass a callback and get your data there:
context.Load(context.GetTblAdminsQuery(), LoadCompleted, null);
and:
public void LoadCompleted(LoadOperation<YOUR_ENTITY_TYPE> op)
{
foreach(var item in op.Entities)
{
//item is your entity, you can get item.adminID
}
}