I am using C# and the Entity Framework to access a MySQL database.
I am grabbing the results of a stored procedure, and trying to turn them into a list of objects, However whenever it comes to the part what references a table through a one to many relationship, it fails with the error
There is already an open DataReader associated with this Connection which must be closed first.
The code I am using is here:
using System;
using System.Collections.Generic;
using System.Data.Objects;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using CarHireCommon.DataObjects;
namespace CarHireServer
{
public class DatabaseHandler
{
protected static DatabaseHandler instance;
protected carhireEntities1 Entities;
public static DatabaseHandler GetInstance()
{
if (instance == null)
instance = new DatabaseHandler();
return instance;
}
public DatabaseHandler()
{
Entities = new carhireEntities1();
}
public List<AvailableAssets> GetAvailableAssets(DateTime startDate, DateTime endDate)
{
ObjectResult<asset> res = Entities.GetAvailableAssets(startDate, endDate);
List<AvailableAssets> list = new List<AvailableAssets>();
foreach(var assetRes in res)
{
AvailableAssets asset=new AvailableAssets();
asset.id = assetRes.id;
asset.Comment = assetRes.comments;
asset.Make = assetRes.make;
asset.Model = assetRes.model;
asset.Fuel = assetRes.fuel;
asset.LongTerm = assetRes.longterm;
// This is the line that errors:
asset.Category = assetRes.category.categoryname;
list.Add(asset);
}
return list;
}
}
}
I have allready told it which table the Stored Procedure returns, and the other variables access correctly.
I have also tried doing it the long way with:
var cat = from b in Entities.categories where b.id == assetRes.category_id select b;
asset.Category = cat.FirstOrDefault<category>().categoryname;
However the thing still exceptions with the exact same error.
I found C# Entity Framework: There is already an open DataReader associated with this Connection which must be closed first which will probably help you exactly with this question.
GL!
Related
I don't know why this test fails. I created a new function, tested it manually and it works fine.
After that, I attempted to create test, but it always fails.
I don't know why.
It just should clear all records from DB older than 1,5 year, but variable historyToDelete always has 0 records. There is whole test:
using Microsoft.EntityFrameworkCore;
using NUnit.Framework;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using TeamsAllocationManager.Contracts.EmployeeWorkingTypeHistory;
using TeamsAllocationManager.Database;
using TeamsAllocationManager.Domain.Models;
using TeamsAllocationManager.Infrastructure.Handlers.EmployeeWorkingHistory;
namespace TeamsAllocationManager.Tests.Handlers.EmployeeWorkingHistory
{
[TestFixture]
public class ClearOldEmployeeWorkingTypeHistoryRecordsHandlerTest
{
private readonly ApplicationDbContext _context;
public ClearOldEmployeeWorkingTypeHistoryRecordsHandlerTest()
{
DbContextOptions<ApplicationDbContext> options = new DbContextOptionsBuilder<ApplicationDbContext>()
.UseInMemoryDatabase(databaseName: GetType().Name)
.Options;
_context = new ApplicationDbContext(options);
}
[SetUp]
public void SetupBeforeEachTest()
{
_context.ClearDatabase();
var employeeWorkingTypeHistory1 = new EmployeeWorkingTypeHistoryEntity
{
EmployeeId = Guid.Parse("d6951ec1-c865-41bb-8b83-0fcd81745579"),
WorkspaceType = 0,
Created = new DateTime(2000, 01, 01)};
var employeeWorkingTypeHistory2 = new EmployeeWorkingTypeHistoryEntity
{
EmployeeId = Guid.Parse("8a6c4e1c-2c6d-4b70-a507-7bdae5f75429"),
WorkspaceType = 0,
Created = DateTime.Now
};
_context.EmployeeWorkingTypeHistory.Add(employeeWorkingTypeHistory1);
_context.EmployeeWorkingTypeHistory.Add(employeeWorkingTypeHistory2);
_context.SaveChanges();
}
[Test]
public async Task ShouldClearHistory()
{
// given
int numberOfHistoryToClear = 1;
int expectedInDatabase = _context.EmployeeWorkingTypeHistory.Count() - numberOfHistoryToClear;
var command = new ClearOldEmployeeWorkingTypeHistoryRecordsCommand();
var deletionDate = command.TodayDate.AddMonths(-18);
var historyToDelete = await _context.EmployeeWorkingTypeHistory
.Where(ewth => deletionDate > ewth.Created)
.ToListAsync();
var commandHandler = new ClearOldEmployeeWorkingTypeHistoryRecordsHandler(_context);
// when
bool result = await commandHandler.HandleAsync(command);
// then
Assert.IsTrue(result);
Assert.AreEqual(expectedInDatabase, _context.EmployeeWorkingTypeHistory.Count());
//Assert.IsFalse(_context.EmployeeWorkingTypeHistory.Any(ewth => historyToDelete.Contains(ewth.Id)));
}
}
}
If I found out why it fails, I will fix whole test but now I am stuck.
#Update 1
I found a issue. When im creating dbContext in SetupBeforeEachTest, im setting up Created to 2000.01.01. There is everything ok, but when im going out from this to the first test, when i checking up a DB i always have current date, not provided in SetupBeforeEach (2021.12.27)
SaveChanges when creating record updating Created date, so if you want to change Created date to test in future, you need to create new record first, then save changes, update it and save changes again.
Try to call the SetupBeforeEachTest() method in your ShouldClearHistory() method.
I have tried to search for this but every example I find has a problem like them actually having the same namespace as their class or something.
I am simply trying to start using Linq. When I add new item Host is localhost. I have my database in Visualstudio and my project name is different than the DataContext name but I can't get it initialized. I get error:
'LinkedContext' is a namespace but is used like a type'
here is code...
namespace TryAgain
{
class Program
{
static void Main(string[] args)
{
LinkedContext db = new LinkedContext();
}
}
}
LinkedContext doesn't work? In settings of the Database Diagram it says the Entity Namespace is 'LinkedContext' So what am I missing. I thought I saw you could run that one line of code to connect your database that is already in VisualStudio due to adding a new item and then start playing with it? I just want to be able to practice with a database! Do stuff like:
var example = from x in example.Table
orderby x.field
select x;
you need using LinkedContext at the top of your file. the error you’re getting is telling you LinkedContext is a namespace but you’re treating like a type, ie a class. once you define it at the top you can then use the type that you need within that namespace.
added "using LinkedContext" to the top of code then also had to use LinkedDataContext not just LinkedContext:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using LinkedContext;
namespace TryAgain
{
class Program
{
static void Main(string[] args)
{
LinkedDataContext db = new LinkedDataContext();
var example = from x in db.employees
orderby x.employee_id
select x;
foreach (var whatever in example)
{
Console.WriteLine(whatever.name);
}
I'm playing with Entity Framework, and I have a Unit Test project that I want to exercise what I've done so far. I'd like to have it not actually update my test database when it's done. If I was working in SQL I would create a transaction and then roll it back at the end.
How can I do the same thing here?
As I understand it, context.SaveChanges(); is effectively doing the write to the database. And if I don't have that, then allCartTypes is empty after I assign it context.CarTypes.ToList()
Here's an example of one of my Test classes.
using System;
using System.Diagnostics;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Trains;
using System.Linq;
namespace TrainsTest
{
[TestClass]
public class TestCarType : TestBase
{
[TestMethod]
public void TestCarTypeCreate_Success()
{
var tankerCarType = new CarType {Name = "Tanker"};
var boxCarType = new CarType { Name = "Box" };
using (var context = new TrainEntities())
{
context.CarTypes.Add(tankerCarType);
context.CarTypes.Add(boxCarType);
context.SaveChanges();
var allCartTypes = context.CarTypes.ToList();
foreach (var cartType in allCartTypes)
{
Debug.WriteLine(cartType.CarTypeId + " - " + cartType.Name);
}
}
}
}
}
I know I'm missing something fundamental, but I don't know what it is. and my googling has been fruitless.
There's a MSDN article about ef transactions.
http://msdn.microsoft.com/en-gb/library/vstudio/bb738523(v=vs.100).aspx
I have an Oracle package that gives a list of facilities based on user ID. It is used to determine access. We have several projects that use this package already but they are all VB and WebForms - we are moving over to C# and MVC and this is the first project like that utilizing this package.
When attempting to run a query in the package, I get a System.InvalidOperationException: The number of parameters does not match number of values for stored procedure.
Procedure spec (I do not have access to the body and this part cannot be edited as it is used extensively in other applications):
Procedure GetFacilitiesByUser
(
p_EmpNo IN int,
cur_OUT out sys_refcursor
);
And my C#:
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Common;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.Practices.EnterpriseLibrary.Common;
using Microsoft.Practices.EnterpriseLibrary.Data;
using Microsoft.Practices.EnterpriseLibrary.Data.Oracle;
namespace MvcApplication1.DataAccess
{
public class InpatientSecurity
{
public List<string> GetHospitals(int EmployeeNumber)
{
var response = new List<string>() { };
object[] _params = { EmployeeNumber };
IDataReader dr = ExecuteQuery(
"connection string",
"datawarehouse.Access.GetFacilitiesByUser",
_params
);
while (dr.Read())
{
response.Add("test");
}
return response;
}
private IDataReader ExecuteQuery(string provider, string procedure, params object[] args)
{
var _db = new OracleDatabase(provider);
object[] objArr = new object[args.Length];
args.CopyTo(objArr, 0);
if (args.Length > 1)
{
objArr[objArr.Length - 1] = System.DBNull.Value;
}
IDataReader reader = _db.ExecuteReader(procedure, objArr); /* Exception thrown here */
_db = null;
return reader;
}
}
}
I did not write the original VB code used to access this procedure, this is just a
As usual, I figured it out shortly after posting. The objArr array needs to be of length 2, I guess to take into account the ref cursor? Changing the following line in ExecuteQuery() fixed the issue.
Change this:
object[] objArr = new object[args.Length];
To this:
object[] objArr = new object[args.Length + 1];
I have a db4o database that was generate by a Java app and I'm trying to read it using a C# app.
However, when running the following line of code:
IObjectContainer db = Db4oEmbedded.OpenFile(#"..\..\..\Databases\people.db4o");
I get the following error:
Unable to cast object of type
'Db4objects.Db4o.Reflect.Generic.GenericObject' to type
'Db4objects.Db4o.Ext.Db4oDatabase'.
Any ideas? I know there are person objects that contain personId fields (along with others) in the DB. I'm using db4o version 8. I'm not sure what version was used to generate the database.
The entire program is:
using System;
using System.Collections.Generic;
using System.Linq;
using Db4objects.Db4o;
using Db4objects.Db4o.Config;
using MyCompany.Domain;
namespace MyCompany.Anonymizer
{
internal class Program
{
// Private methods.
private static IEmbeddedConfiguration ConfigureAlias()
{
IEmbeddedConfiguration configuration = Db4oEmbedded.NewConfiguration();
configuration.Common.AddAlias(new TypeAlias("com.theircompany.Person", "MyCompany.Domain.Person, MyCompany.Domain"));
configuration.Common.Add(new JavaSupport());
return configuration;
}
private static void Main(string[] args)
{
IObjectContainer db = Db4oEmbedded.OpenFile(#"..\..\..\Databases\people.db4o");
try
{
IList<Person> result = db.Query<Person>();
for (int i = 0; i < result.Count; i++)
{
Person person = result[i];
Console.WriteLine(string.Format("Person ID: {0}", person.personId));
}
}
finally
{
db.Close();
}
}
}
}
The most common scenario in which this exception is thrown is when db4o fails to resolve the type of a stored object.
In your case, db4o is failing to read one of its internal objects which makes me believe you have not passed the configuration to the OpenFile() method (surely, the code you have posted is not calling ConfigureAlias() method);
Keep in mind that as of version 8.0 no further improvement will be done regarding cross platform support (you can read more details here).