The underlying connection was closed error while using .Include on EF objects - wcf

Following line of code gives me an error saying "The underlying connection was closed".
return this.repository.GetQuery<Countries>().Include(g => g.Cities).AsEnumerable().ToList();
But if I remove .Include(g => g.cities) it works fine.
this code is written in one of the operation in my WCF service, and I try to test it using WCF test client. I tried by calling this operation from MVC application also, and the same issue was occurring there too.
Also, i am using generic repository with entity framework
Repository code (only few important extract)
Constructor:
public GenericRepository(DbContext objectContext)
{
if (objectContext == null)
throw new ArgumentNullException("objectContext");
this._dbContext = objectContext;
this._dbContext.Configuration.LazyLoadingEnabled = false;
this._dbContext.Configuration.ProxyCreationEnabled = false;
}
GetQuery method:
public IQueryable<TEntity> GetQuery<TEntity>() where TEntity : class
{
var entityName = GetEntityName<TEntity>();
return ((IObjectContextAdapter)DbContext).ObjectContext.CreateQuery<TEntity>(entityName);
}
Attempt#1
Created following overloads in repository code:
public IQueryable<TEntity> GetQuery<TEntity>(params string[] includes) where TEntity : class
{
var entityName = GetEntityName<TEntity>();
IQueryable<TEntity> query = ((IObjectContextAdapter)DbContext).ObjectContext.CreateQuery<TEntity>(entityName);
foreach(string include in includes)
{
query = query.Include(include);
}
return query;
}
public IQueryable<TEntity> GetQuery<TEntity>(Expression<Func<TEntity, bool>> predicate, params string[] includes) where TEntity : class
{
return GetQuery<TEntity>(includes).Where(predicate);
}
WCF is now trying to execute following line of code:
return this.repository.GetQuery<Countries>("Cities").AsEnumerable().ToList()
But it still gives the same error of "The underlying connection was closed". I tested it in WCF test client. However, when I debug the repository code it shows the navigation object getting included in result, but the issue seems occurring while trying to pass the output to client (WCF test client, or any other client)

After looking at the code you've now posted, I can conclude that, indeed, your DbContext is being closed at the end of the GetQuery method, and is thus failing when you try to use include. What you might want to do to solve it is to have an optional params variable for the GetQuery method that will take in some properties to be included, and just do the include right in the GetQuery method itself.

Related

Executing a Remote.Linq expression against data

I'm using Remote.Linq to serialise / deserialise my Expressions as I want to create the ability to send dynamic expressions from a client application to our web services. Standard .NET expressions cannot be serialised so I'm using Remote.Linq instead.
However, I cannot see how to execute the Expression. Normally I would invoke the Compile() and Invoke() methods to execute the Expression against the data. But Remote.Linq expressions don't support such methods.
The following unit test may explain more clearly what I'm trying to achieve.
[TestMethod]
public void SerializeLinqExpressionsTests()
{
var testdata = GetTestdata();
Expression<Func<ModuleEntityAdmins, ModuleEntityAdmin>> expr1 = m => m.Modules.Find(q => q.Id == 1);
var remoteExpression1 = expr1.ToRemoteLinqExpression();
string strexpr1 = SerialiseExpression(remoteExpression1);
try
{
var deserexpr1 = DeserialiseExpression<Remote.Linq.Expressions.LambdaExpression>(strexpr1.NormalizeJsonString());
//what is the equivalent of doing this with a Remote.Linq Expression?
var compiled1 = expr1.Compile();
var result = compiled1.Invoke(testdata);
Assert.IsNotNull(result);
Assert.IsTrue(result.Id == 1);
}
catch (Exception e)
{
Console.WriteLine(e.Message);
Assert.Fail("Error deserialising LINQ expression tree");
}
}
How do you invoke a Remote.Linq expression?
A remote linq expression may be converted back into a system linq expression and be compiled and executed as such.
However, this is not what you actually want when sending expressions to a server to query data. On server side you want to use the Execute extension methods to execute your expression against a data source. Make sure to add a using for namespace Remote.Linq.Expressions.
Here's the sample code from Remote.Linq source repo:
using Remote.Linq.Expressions;
public interface IQueryService
{
IEnumerable<DynamicObject> ExecuteQuery(Expression queryExpression);
}
public class QueryService : IQueryService, IDisposable
{
// any linq provider e.g. entity framework, nhibernate, ...
private IDataProvider _datastore = new ObjectRelationalMapper();
// you need to be able to retrieve an IQueryable by type
private Func<Type, IQueryable> _queryableProvider = type => _datastore.GetQueryableByType(type);
public IEnumerable<DynamicObject> ExecuteQuery(Expression queryExpression)
{
// `Execute` is an extension method provided by Remote.Linq
// it applies an expression to a data source and returns the result
return queryExpression.Execute(queryableProvider: _queryableProvider);
}
public void Dispose() => _datastore.Dispose();
}
Also, there are additional nuget packages for expression execution with EF and EF Core, so you can simply provide a DbContext to the Execute method.
In addition you may want to check out the demos/samples found in the project's github repo.

Symfony Dependency injection with services

Trying to create a service that logs information to a database. The service has to call the Doctrine\ORM\EntityManager in the constuctor, but I keep getting this error:
Catchable Fatal Error: Argument 1 passed to AppBundle\Service\EmailLoggerManager::__construct() must be an instance of Doctrine\ORM\EntityManager, none given, called in /Users/augustwhitlock/Desktop/symfony/SymfonyRepositories/forms/src/AppBundle/Controller/DefaultController.php on line 45 and defined
Here is what I have in my service file
namespace AppBundle\Service;
use Doctrine\ORM\EntityManager;
use AppBundle\Entity\Logger;
class EmailLoggerManager
{
private $em;
public function __construct(EntityManager $em)
{
$this->em = $em;
}
public function logMessageToDatabase($type, $message, $date)
{
$logger = new Logger();
$logger->setMessageType = $type;
$logger->setMessageText = $message;
$logger->setMessageDate = $date;
$this->em->persist($logger);
$this->em->flush();
}
This I how I'm handling the injection of the EntityManager.
app.email_logger_manager:
class: AppBundle\Services\EmailLoggerManager
arguments: ['#doctrine.orm.entity_manager']
At this point I'm just learning about service and trying different things out. But this doesn't want to work.
Here is the edit of the DefaultController. I'm adding lines 45 and 46. There is nothing about it except the class definition.
$emailLoggerManager = new EmailLoggerManager();
$emailLoggerManager->logMessageToDatabase('Info', 'Hiya', new \DateTime());
return new Response('Message Logged');
The whole concept behind the class is to just use doctrine in the service to log things to the database, clearing my controllers from having to be clogged of all that code.
You should call the service from the controller as follows:
$this->get('app.email_logger_manager')
->logMessageToDatabase('Info', 'Hiya', new \DateTime());
instead of instantiating the class directly in the controller.
Furthermore it is advisable to pass the "#doctrine" service instead of #doctrine.orm.entity_manager due to the possibility of the EntityManager being closed.
The constructor would than have to receive Doctrine\Bundle\DoctrineBundle\Registry instead of Doctrine\ORM\EntityManager

Ninject Moqing Kernel (what does reset do?)

I have an interface that I'm using with a couple different concrete classes. What I wish is that there was something like this...
_kernel.GetMock<ISerializeToFile>().Named("MyRegisteredName")
.Setup(x => x.Read<ObservableCollection<PointCtTestDataInput>>(
It.IsAny<string>()));
The project I'm working on uses the service locator pattern - anti-pattern which I'm getting less fond of all the time...
Originally I tried..
[ClassInitialize]
public static void ClassInitialize(TestContext testContext)
{
_kernel = new MoqMockingKernel();
}
[TestInitialize]
public void TestInitialize()
{
_kernel.Reset();
ServiceLocator.SetLocatorProvider(
() => new NinjectServiceLocator(_kernel));
_kernel.Bind<ISerializeToFile>().ToMock()
.InSingletonScope().Named("ObjectToFile");
_kernel.GetMock<ISerializeToFile>()
.Setup(x => x.Read<ObservableCollection<PointCtTestDataInput>>(
It.IsAny<string>()));
_kernel.GetMock<ISerializeToFile>()
.Setup(x => x.Save<ObservableCollection<PointCtTestDataInput>>(
It.IsAny<ObservableCollection<PointCtTestDataInput>>(),
It.IsAny<string>()));
}
I got the standard Ninject error stating that more than one matching binding is available. So, I moved _kernel = new MoqMockingKernel(); into the TestInitialize, and then that error went away... Perhaps I'm incorrectly guess at what _kernel.Reset() does?
Reset removes any instance from the cache. It does not delete existing bindings. So the second test will have the ISerializeToFile twice.

Per- request based Object Context and Complied Query Performance with Entity Framework

I'm currently working with WCF services application and we've created per request based Object Context of Entity framework. In the entity framework queries, we've used Complied Query mechanism, however, expected performance could not be achieved at the moment. I suspect it is due to the nature of Object Context(Per request based),as Complied queried depends on Object Context. Is it so?
Code Sample
private static readonly Func<MyContext, IQueryable<Order>> _compiledObjectQuery = CompiledQuery.Compile<MyContext, IQueryable<Order>>(
(ctx) => from Order in ctx.Orders
.Include("OrderType")
.Include("OrderLines")
select Order
);
protected override IQueryable<Order> OrderQuery
{
get { return _compiledObjectQuery.Invoke(Context); }
}
Context Creating
public OPDbContext DbContext
{
get
{
if(_dbConext == null)
{
_dbConext = new OPDbContext(Context, true);
}
return _dbConext;
}
}
Castle is used to inject Object Context per request base

Can I stop my WCF generating ArrayOfString instead of string[] or List<string>

I am having a minor problem with WCF service proxies where the message contains List<string> as a parameter.
I am using the 'Add Service reference' in Visual Studio to generate a reference to my service.
// portion of my web service message
public List<SubscribeInfo> Subscribe { get; set; }
public List<string> Unsubscribe { get; set; }
These are the generated properties on my MsgIn for one of my web methods.
You can see it used ArrayOfString when I am using List<string>, and the other takes List<SubscribeInfo> - which matches my original C# object above.
[System.Runtime.Serialization.DataMemberAttribute(EmitDefaultValue=false)]
public System.Collections.Generic.List<DataAccess.MailingListWSReference.SubscribeInfo> Subscribe {
get {
return this.SubscribeField;
}
set {
if ((object.ReferenceEquals(this.SubscribeField, value) != true)) {
this.SubscribeField = value;
this.RaisePropertyChanged("Subscribe");
}
}
}
[System.Runtime.Serialization.DataMemberAttribute(EmitDefaultValue=false)]
publicDataAccess.MailingListWSReference.ArrayOfString Unsubscribe {
get {
return this.UnsubscribeField;
}
set {
if ((object.ReferenceEquals(this.UnsubscribeField, value) != true)) {
this.UnsubscribeField = value;
this.RaisePropertyChanged("Unsubscribe");
}
}
}
The ArrayOfString class generated looks like this. This is a class generated in my code - its not a .NET class. It actually generated me a class that inherits from List, but didn't have the 'decency' to create me any constructors.
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.Runtime.Serialization", "3.0.0.0")]
[System.Runtime.Serialization.CollectionDataContractAttribute(Name="ArrayOfString", Namespace="http://www.example.com/", ItemName="string")]
[System.SerializableAttribute()]
public class ArrayOfString : System.Collections.Generic.List<string> {
}
The problem is that I often create my message like this :
client.UpdateMailingList(new UpdateMailingListMsgIn()
{
Email = model.Email,
Name = model.Name,
Source = Request.Url.ToString(),
Subscribe = subscribeTo.ToList(),
Unsubscribe = unsubscribeFrom.ToList()
});
I really like the clean look this gives me.
Now for the actual problem :
I cant assign a List<string> to the Unsubscribe property which is an ArrayOfString - even though it inherits from List. In fact I cant seem to find ANY way to assign it without extra statements.
I've tried the following :
new ArrayOfString(unsubscribeFrom.ToList()) - this constructor doesn't exist :-(
changing the type of the array used by the code generator - doesn't work - it always gives me ArrayOfString (!?)
try to cast List<string> to ArrayOfString - fails with 'unable to cast', even though it compiles just fine
create new ArrayOfString() and then AddRange(unsubscribeFrom.ToList()) - works, but I cant do it all in one statement
create a conversion function ToArrayOfString(List<string>), which works but isn't as clean as I want.
Its only doing this for string, which is annoying.
Am i missing something? Is there a way to tell it not to generate ArrayOfString - or some other trick to assign it ?
Any .NET object that implements a method named "Add" can be initialized just like arrays or dictionaries.
As ArrayOfString does implement an "Add" method, you can initialize it like this:
var a = new ArrayOfString { "string one", "string two" };
But, if you really want to initialize it based on another collection, you can write a extension method for that:
public static class U
{
public static T To<T>(this IEnumerable<string> strings)
where T : IList<string>, new()
{
var newList = new T();
foreach (var s in strings)
newList.Add(s);
return newList;
}
}
Usage:
client.UpdateMailingList(new UpdateMailingListMsgIn()
{
Email = model.Email,
Name = model.Name,
Source = Request.Url.ToString(),
Subscribe = subscribeTo.ToList(),
Unsubscribe = unsubscribeFrom.To<ArrayOfString>()
});
I prefer not to return generic types across a service boundary in the first place. Instead return Unsubscribe as a string[], and SubscriptionInfo as SubscriptionInfo[]. If necessary, an array can easily be converted to a generic list on the client, as follows:
Unsubscribe = new List<string>(unsubscribeFrom);
Subscribe = new List<SubscriptionInfo>(subscribeTo);
Too late but can help people in the future...
Use the svcutil and explicitly inform the command line util that you want the proxy class to be serialized by the XmlSerializer and not the DataContractSerializer (default). Here's the sample:
svcutil /out:c:\Path\Proxy.cs /config:c:\Path\Proxy.config /async /serializer:XmlSerializer /namespace:*,YourNamespace http://www.domain.com/service/serviceURL.asmx
Note that the web service is an ASP.NET web service ok?!
If you are using VS 2008 to consume service then there is an easy solution.
Click on the "Advanced..." button on the proxy dialog that is displayed when you add a Service Reference. In the Collection Type drop down you can select System.Generic.List. The methods returning List should now work properly.
(Hope this is what you were asking for, I'm a little tired and the question was a tad difficult for me to read.)