EF: How to enclose context object in a using statement? - entity-framework

Let's say I have the following classes Customer.cs, a context OfficeContext.cs, and a repository OfficeRepository.cs. Knowing that the context use a connection object, so it's advised to enclose it in a using statement:
public List<Customer> GetAllCustomersWithOrders()
{
using(var oContext = new OfficeContext())
{
//Code here....
}
}
My question is what if I want to re-use some of the code already in the repository? For instance, what if I want to display all the customers that ordered products but didn't receive them yet, do I need to duplicate the code?
public List<Customer> GetCustomersNotReceiveProducts()
{
using(var oContext = new OfficeContext())
{
//Re-use GetAllCustomersWithOrders() here???...
}
}
But as you can see, each time access a method, I also open instantiate a new context object. Is there any way to deal with that?

What I do is have my repositories implement IDisposable.
Then have two constructors (one default) that instaniates a new context that holds it as a class level variable. And another constructor that takes a context and uses that internally.
The on the dispose of the class the context is disposed (if the current repository instatiated it).
This removes the context out of the method level and moves it to the class level. My functions keep everything in IQueryable so one function can call another function and perform additional refinements before the database it hit.
Exmaple:
public class MemberRepository : IDisposable
{
OfficeContext db;
bool isExternalDb = false;
public MemberRepository()
{
db = new OfficeContext();
isExternalDb = false;
}
public MemberRepository(OfficeContext db)
{
this.db = db;
isExternalDb = true;
}
public IQueryable<Member> GetAllMembers()
{
var members= db.Members
return members;
}
public IQueryable<Member> GetActiveMembers()
{
var members = GetAllMembers();
var activeMembers = members.Where(m => m.isActive == true);
return activeMembers;
}
public void Dispose()
{
if (isExternalDb == false)
{
db.Dispose();
}
}
}
Then where I use the repository, I do a using at that level:
using(var memberRepository = new MemberRepository())
{
var members = memberRepository.GetActiveMembers();
}

Related

How to mock Entity Framework in a N-Layer Architecture

I have a N-Layer application with Entity Framework (Code-First approach). Now I want to automatize some tests. I am using Moq framework. I am finding some problem about writing the tests. Perhaps my architecture is wrong? With wrong, I mean that I wrote components that are not well isolated and so they are not testable. I do not really like this... Or perhaps, I simply cannot use correctly moq framework.
I let you see my architecture:
At every level I inject my context in the constructor of the class.
The Facade:
public class PublicAreaFacade : IPublicAreaFacade, IDisposable
{
private UnitOfWork _unitOfWork;
public PublicAreaFacade(IDataContext context)
{
_unitOfWork = new UnitOfWork(context);
}
}
The BLL:
public abstract class BaseManager
{
protected IDataContext Context;
public BaseManager(IDataContext context)
{
this.Context = context;
}
}
The Repository:
public class Repository<TEntity>
where TEntity : class
{
internal PublicAreaContext _context;
internal DbSet<TEntity> _dbSet;
public Repository(IDataContext context)
{
this._context = context as PublicAreaContext;
}
}
IDataContext is an interface that is implemented by my DbContext:
public partial class PublicAreaContext : DbContext, IDataContext
Now, how I mock EF and how I write the tests:
[TestInitialize]
public void Init()
{
this._mockContext = ContextHelper.CreateCompleteContext();
}
Where ContextHelper.CreateCompleteContext() is:
public static PublicAreaContext CreateCompleteContext()
{
//Here I mock my context
var mockContext = new Mock<PublicAreaContext>();
//Here I mock my entities
List<Customer> customers = new List<Customer>()
{
new Customer() { Code = "123455" }, //Customer with no invoice
new Customer() { Code = "123456" }
};
var mockSetCustomer = ContextHelper.SetList(customers);
mockContext.Setup(m => m.Set<Customer>()).Returns(mockSetCustomer);
...
return mockContext.Object;
}
And here how I write my test:
[TestMethod]
public void Success()
{
#region Arrange
PrepareEasyPayPaymentRequest request = new PrepareEasyPayPaymentRequest();
request.CodiceEasyPay = "128855248542874445877";
request.Servizio = "MyService";
#endregion
#region Act
PublicAreaFacade facade = new PublicAreaFacade(this._mockContext);
PrepareEasyPayPaymentResponse response = facade.PrepareEasyPayPayment(request);
#endregion
#region Assert
Assert.IsTrue(response.Result == it.MC.WebApi.Models.ResponseDTO.ResponseResult.Success);
#endregion
}
Here It seems It works everything correctly!!! And It looks like my architecture is correct. But what if I want to insert/update an Entity? Nothing work anymore! I explain why:
As you can see I pass a *Request object (it is the DTO) to the facade, then in my TOA I generate my entity from the propertiess of the DTO:
private PaymentAttemptTrace CreatePaymentAttemptTraceEntity(string customerCode, int idInvoice, DateTime paymentDate)
{
PaymentAttemptTrace trace = new PaymentAttemptTrace();
trace.customerCode = customerCode;
trace.InvoiceId = idInvoice;
trace.PaymentDate = paymentDate;
return trace;
}
PaymentAttemptTrace is the Entity I will inserto to Entity Framework.. It is not mocked and I cannot inject it. So even if I pass my mocked context (IDataContext), when I try to insert an Entity that is not mocked my test fails!
Here that doubt about I have a wrong architecture has raised!
So, what's wrong? The architecture or the way I use moq?
Thank you for help
UPDATE
Here how I test my code.. For example, I want to test the trace of a payment..
Here the test:
[TestMethod]
public void NoPaymentDate()
{
TracePaymentAttemptRequest request = new TracePaymentAttemptRequest();
request.AliasTerminale = "MyTerminal";
//...
//I create my request object
//You can see how I create _mockContext above
PublicAreaFacade facade = new PublicAreaFacade(this._mockContext);
TracePaymentAttemptResponse response = facade.TracePaymentAttempt(request);
//My asserts
}
Here the facade:
public TracePaymentAttemptResponse TracePaymentAttempt(TracePaymentAttemptRequest request)
{
TracePaymentAttemptResponse response = new TracePaymentAttemptResponse();
try
{
...
_unitOfWork.PaymentsManager.SavePaymentAttemptResult(
easyPay.CustomerCode,
request.CodiceTransazione,
request.EsitoPagamento + " - " + request.DescrizioneEsitoPagamento,
request.Email,
request.AliasTerminale,
request.NumeroContratto,
easyPay.IdInvoice,
request.TotalePagamento,
paymentDate);
_unitOfWork.Commit();
response.Result = ResponseResult.Success;
}
catch (Exception ex)
{
response.Result = ResponseResult.Fail;
response.ResultMessage = ex.Message;
}
return response;
}
Here how I developed the PaymentsManager:
public PaymentAttemptTrace SavePaymentAttemptResult(string customerCode, string transactionCode, ...)
{
//here the problem... PaymentAttemptTrace is the entity of entity framework.. Here i do the NEW of the object.. It should be injected, but I think it would be a wrong solution
PaymentAttemptTrace trace = new PaymentAttemptTrace();
trace.customerCode = customerCode;
trace.InvoiceId = idInvoice;
trace.PaymentDate = paymentDate;
trace.Result = result;
trace.Email = email;
trace.Terminal = terminal;
trace.EasypayCode = transactionCode;
trace.Amount = amount;
trace.creditCardId = idCreditCard;
trace.PaymentMethod = paymentMethod;
Repository<PaymentAttemptTrace> repository = new Repository<PaymentAttemptTrace>(base.Context);
repository.Insert(trace);
return trace;
}
In the end how I wrote the repository:
public class Repository<TEntity>
where TEntity : class
{
internal PublicAreaContext _context;
internal DbSet<TEntity> _dbSet;
public Repository(IDataContext context)
{
//the context is mocked.. Its type is {Castle.Proxies.PublicAreaContextProxy}
this._context = context as PublicAreaContext;
//the entity is not mocked. Its type is {PaymentAttemptTrace} but should be {Castle.Proxies.PaymentAttemptTraceProxy}... so _dbSet result NULL
this._dbSet = this._context.Set<TEntity>();
}
public virtual void Insert(TEntity entity)
{
//_dbSet is NULL so "Object reference not set to an instance of an object" exception is raised
this._dbSet.Add(entity);
}
}
Your architecture looks good, but the implementation is flawed. It is leaking abstraction.
In your diagram the Façade layer depends only on the BLL but when you look at the PublicAreaFacade's constructor you will see that in reality it has a direct dependency to an interface from the Repository layer:
public PublicAreaFacade(IDataContext context)
{
_unitOfWork = new UnitOfWork(context);
}
This should not be. It should only take its direct dependency as input -- the PaymentsManager or -- even better -- an interface of it:
public PublicAreaFacade(IPaymentsManager paymentsManager)
{
...
}
The concequence is that your code becomes way more testable. When you look at your tests now you see that you have to mock the most inner layer of your system (i.e. the IDataContext and even its entity accessors Set<TEntity>) altough you are testing one of the most outer layers of your system (the PublicAreaFacade class).
This is how a unit test for the TracePaymentAttempt method would look like if the PublicAreaFacade only depended on IPaymentsManager:
[TestMethod]
public void CallsPaymentManagerWithRequestDataWhenTracingPaymentAttempts()
{
// Arrange
var pm = new Mock<IPaymentsManager>();
var pa = new PulicAreaFacade(pm.Object);
var payment = new TracePaymentAttemptRequest
{
...
}
// Act
pa.TracePaymentAttempt(payment);
// Assert that we call the correct method of the PaymentsManager with the data from
// the request.
pm.Verify(pm => pm.SavePaymentAttemptResult(
It.IsAny<string>(),
payment.CodiceTransazione,
payment.EsitoPagamento + " - " + payment.DescrizioneEsitoPagamento,
payment.Email,
payment.AliasTerminale,
payment.NumeroContratto,
It.IsAny<int>(),
payment.TotalePagamento,
It.IsAny<DateTime>()))
}
Pass IUnitOfWork into the Facade or BLL layer constructor, whichever one makes calls on the unit of work directly. Then you can setup what the Mock<IUnitOfWork> is returning in your tests. You should not need to pass IDataContext to everything except maybe the repo constructors and the unit of work.
For example, if the Facade has a method PrepareEasyPayPayment that makes a repo call through a UnitOfWork call, setup the mock like this:
// Arrange
var unitOfWork = new Mock<IUnitOfWork>();
unitOfWork.Setup(x => x.PrepareEasyPayPaymentRepoCall(request)).Returns(true);
var paymentFacade = new PaymentFacade(unitOfWork.Object);
// Act
var result = paymentFacade.PrepareEasyPayPayment(request);
Then you've mocked out the data call and can more easily test your code in the Facade.
For the insert testing, you should have a Facade method like CreatePayment which takes a PrepareEasyPayPaymentRequest. Inside that CreatePayment method, it should reference the repo, probably through the unit of work, like
var result = _unitOfWork.CreatePaymentRepoCall(request);
if (result == true)
{
// yes!
}
else
{
// oh no!
}
What you want to mock for unit testing is that this create/insert repo call returns true or false so you can test the code branches after the repo call has completed.
You can also test that the insert call was made as expected, but that's usually not as valuable unless the parameters for that call have a lot of logic involved in building them.
it sounds like you need to change the code a little bit. Newing things introduces hardcoded dependencies and makes them untestable, so try to abstract them away. Maybe you can hide everything to do with EF behind another layer, then all you have to do is mock that particular layer layer and never touch EF.
You can use this open source framework for unit testing which is good to mock entity framework dbcontext
https://effort.codeplex.com/
Try this will help you to mock your data efficiently.

Entity Framework as DAL how to implement Update and Delete correctly

I'm writing a DAL class using EF4.0, I've read
http://www.codeproject.com/Articles/43367/ADO-NET-Entity-Framework-as-Data-Access-Layer
and
http://msdn.microsoft.com/en-us/magazine/cc700340.aspx
But when I test their code, I meet some problem with the Update and Delete method.
The DAL class all code is below:
public class FriendlinkDA : IDisposable
{
private EdiBlogEntities context;
public FriendlinkDA()
{
context = new EdiBlogEntities();
}
public void Dispose()
{
context.Dispose();
}
public FriendLink GetFriendLink(Guid id)
{
return context.FriendLink.FirstOrDefault(f => f.Id == id);
}
public void Update(FriendLink model)
{
// Way 1: (throw exception)
//context.Attach(model);
//model.SetAllModified(context);
//context.SaveChanges();
// Way 2:
EntityKey key;
object originalItem;
key = context.CreateEntityKey("FriendLink", model);
if (context.TryGetObjectByKey(key, out originalItem))
{
context.ApplyCurrentValues(key.EntitySetName, model);
//context.ApplyPropertyChanges(key.EntitySetName, model);
}
context.SaveChanges();
}
public void Delete(FriendLink model)
{
// Way 1:
context.Attach(model);
context.DeleteObject(model);
context.SaveChanges();
// Way 2:
//var item = context.FriendLink.FirstOrDefault(f => f.Id == model.Id);
//context.DeleteObject(item);
//context.SaveChanges();
}
}
The extension method is:
public static void SetAllModified<T>(this T entity, ObjectContext context) where T : IEntityWithKey
{
var stateEntry = context.ObjectStateManager.GetObjectStateEntry(entity.EntityKey);
var propertyNameList = stateEntry.CurrentValues.DataRecordInfo.FieldMetadata.Select
(pn => pn.FieldType.Name);
foreach (var propName in propertyNameList)
stateEntry.SetModifiedProperty(propName);
}
In the application, I am use the DAL like this:
// Delete
using (var optFriendlink = new FriendlinkDA())
{
var test = optFriendlink.GetFriendLink(new Guid("81F58198-D396-41DE-A240-FC306C7343E8"));
optFriendlink.Delete(test);
}
// Update
using (var optFriendlink = new FriendlinkDA())
{
var testLink = optFriendlink.GetFriendLink(new Guid("62FD0ACF-40C3-4BAD-B438-38BB540A6080"));
testLink.Title = "ABC";
optFriendlink.Update(testLink);
}
Question 1:
In Delete(), both way 1 and way 2 can work. Which one is better?
Question 2:
In Update(), way 1 give me an exception: The object cannot be attached because it is already in the object context. An object can only be reattached when it is in an unchanged state.
on this statment: context.Attach(model);
but way 2 is fine.
why is this happening? I also attach the model in Delete(), why Delete() is working fine? how I can write the update correctly?
The exception says it all:
An object can only be reattached when it is in an unchanged state.
You change the object in the code snippet under // Update, so that's why it cannot be re-attached.
As to which method is better. Normally you would get an object from a context, dispose of the context, do something with the object and then use a new context to save the object. In that case using Attach is much more comfortable then getting an object by Id first.

How to manage ObjectContext lifetime correctly in multi-tier application using Entity Framework?

I have seen many examples using Entity Framework in MVC3 applications, they are very simple demos which only have one mvc3 web project with edmx inside it.
So, they can use the best practice for open and close connection by "using" statement:
using(var context = new SchoolEntities())
{
// do some query and return View with result.
}
And, It can use lazy load (navigation properties) inside the "using" statment correctly, because the context is not yet
disposed:
foreach(var item in student.Course)
{
// do something with the navigation property Course
}
All things seems to be perfect until it becomes an n-tier application.
I created DAL, BLL, and a MVC3 UI.
The DAL have edmx inside it, and operator classes like SchoolDA.cs:
public class StudentDA()
{
public Student FindStudent(int studentId)
{
using(var context = new SchoolContext())
{
// do query, return a student object.
}
}
}
Then, in the BLL, if I use:
var student = studentDa.FindStudent(103);
then invoke it's navigation property:
student.Course
I will get an error (of course):
The ObjectContext instance has been disposed and can no longer be used for operations that require a connection.
So, I have to change StudentDA.cs like this:
public class StudentDA() : IDisposable
{
private SchoolEntites context;
public StudentDA()
{
context = new SchoolEntities();
}
public void Dispose()
{
context.Dispose();
}
public Student FindStudent(int studentId)
{
// do query, return a student object.
}
}
Then, the BLL will change like this:
public Student FindStudent(int id)
{
using(var studentDa = new StudentDA())
{
// this can access navigation properties without error, and close the connection correctly.
return studentDa.FindStudent(id);
}
}
All things seem to be perfect again until it meet Update() method.
Now, if I want to update a student object which is taken from BLL.FindStudent(), the context.SaveChanges() will return 0, because the context is already disposed in the BLL.FindStudent(), and nothing will be updated to database.
var optStudent = new StudentBO();
var student = optStudent.FindStudent(103);
student.Name = "NewValue";
optStudent.Update(student);
Does anyone have idea on how to use EntityFramework in 3 tire application? or how can I manage the context correctly. I will use navigation propertites very often in the web layer, but I can't always remain connection open to consume the server memory.
There are multiple ways to handle EF context's lifetime. In web apps, usually context is unique for an HttpRequest. For example, if you want to handle this manually in a web application and have a per Thread/HttpRequest EF context, you can do so with the following (Code copied from http://www.west-wind.com/weblog/posts/2008/Feb/05/Linq-to-SQL-DataContext-Lifetime-Management):
internal static class DbContextManager
{
public static DbContext Current
{
get
{
var key = "MyDb_" + HttpContext.Current.GetHashCode().ToString("x")
+ Thread.CurrentContext.ContextID.ToString();
var context = HttpContext.Current.Items[key] as MyDbContext;
if (context == null)
{
context = new MyDbContext();
HttpContext.Current.Items[key] = context;
}
return context;
}
}
}
And then you can easily use:
var ctx = DbContextManager.Current
But I suggest you leave the lifetime management to an IoC framework like Autofac, Castle Windsor, or Ninject which automatically handle the creation/disposal of your registered obejcts along with many other features.
Thanks for your answer Kamyar. I came across this whilst looking for a simple strategy to manage the ObjectContext lifetime without having to use an IoC framework, which seems a bit overkill for my needs.
I also came across your other post here, for disposing of the context at the end of the request.
Thought this might be useful for others coming across this, so just posting my implementation of your code here:
Context manager class -
internal static class MyDBContextManager
{
//Unique context key per request and thread
private static string Key
{
get
{
return string.Format("MyDb_{0}{1}", arg0: HttpContext.Current.GetHashCode().ToString("x"),
arg1: Thread.CurrentContext.ContextID);
}
}
//Get and set request context
private static MyDBContext Context
{
get { return HttpContext.Current.Items[Key] as MyDBContext; }
set { HttpContext.Current.Items[Key] = value; }
}
//Context per request
public static MyDBContext Current
{
get
{
//if null, create new context
if (Context == null)
{
Context = new MyDBContext();
HttpContext.Current.Items[Key] = Context;
}
return Context;
}
}
//Dispose any created context at the end of a request - called from Global.asax
public static void Dispose()
{
if (Context != null)
{
Context.Dispose();
}
}
}
Global.asax (MVC) -
public override void Init()
{
base.Init();
EndRequest +=MvcApplication_EndRequest;
}
private void MvcApplication_EndRequest(object sender, EventArgs e)
{
MyDBContextManager.Dispose();
}

Satisfy Imports in custom ExportProvider

I'd like to know how I can have Imports in my custom ExportProvider. Here's an example of what I'm trying to do:
public class MyExportProvider : ExportProvider
{
private List<Export> _exports;
[Import()]
private IConfig _config;
public MyExportProvider()
base()
{
_exports = new List<Export>();
}
protected override IEnumerable<Export> GetExportsCore(ImportDefinition definition,
AtomicComposition composition)
{
if (!_exports.Any())
Initialize();
return _exports.Where(x => definition.IsConstraintSatisfiedBy(s.Definition);
}
private void Initialize()
{
var contractName = typeof(MyObject).FullName;
var exportDefinition = new ExportDefinition(contractName, null);
var export = new Export(exportDefinition, () => new MyObject(_config));
_exports.Add(export);
}
}
I am adding the provider when I create the CompositionContainer.
Unfortunately, the import is never satisfied. I can see this by setting AllowDefaults = true so my provider is created, but _config is always null.
How can I configure the container and/or provider so the Import will be satisfied?
When you are adding your export provider you are still creating your composition container. Thus I don't see how you can use the not yet created composition container to import parts of your custom export provider.
What I would do is first create a temporary CompositionContainer that will be used to create MyExportProvider.
Afterwards use the MyExportProvider to create your second final CompositionContainer that will be used by the rest of the application.
EDIT:
// this is your real container, only shown here for reference
CompositionContainer container;
public void BootstrapContainerMethod()
{
// Replace this part with the catalogs required to create your export provider.
var catalog = new AggregateCatalog();
catalog.Catalogs.Add(new DirectoryCatalog("./bin", "*.dll"));
// Your temporary container, declared here in local scope
// will be disposed because of using
using (var bootstrapContainer = new CompositionContainer(catalog))
{
var myExportProvider = bootstrapContainer.GetExportedValue<IMyExportProvider>();
// create your real container and optionnally add catalogs (not shown here)
container = new CompositionContainer(myExportProvider);
}
}
You might also consider the problem from another angle. Do you really need to have imports in your custom ExportProvider? I do not know your requirements, but maybe you can make do without having imports.
As an alternative to the dual CompositionContainer solution, you could wire this up in a single export provider, and have it compose itself using the same container. As an example, I've defined the following contract and it's export:
public interface ILogger
{
void Log(string message);
}
[Export(typeof(ILogger))]
public class ConsoleLogger : ILogger
{
public void Log(string message)
{
Console.WriteLine(message);
}
}
And with my example ExportProvider, I expect to be able to import an instance of it:
public class TestExportProvider : ExportProvider
{
private readonly object _lock = new object();
private bool _initialised;
[Import]
public ILogger Logger { get; set; }
public void SetCompositionService(ICompositionService service)
{
if (service == null) throw new ArgumentNullException("service");
lock (_lock)
{
if (!_initialised)
{
InitialiseProvider(service);
}
}
}
private void InitialiseProvider(ICompositionService service)
{
service.SatisfyImportsOnce(this);
_initialised = true;
}
protected override IEnumerable<Export> GetExportsCore(ImportDefinition definition, AtomicComposition atomicComposition)
{
if (_initialised)
{
Logger.Log("Getting available exports for '" + definition.ContractName + "'");
// Do work here.);
return Enumerable.Empty<Export>();
}
return Enumerable.Empty<Export>();
}
}
I provide an instance of an ICompositionService, which CompositionContainer implements, and I perform a first-time initialisation when I call SetCompositionService. It checks to see if it has already been initialised, and if not, goes ahead and calls the SatisfyImportsOnce method on itself.
We would wire this up, something like this:
// Build our catalog.
var catalog = new AssemblyCatalog(typeof(Program).Assembly);
// Create our provider.
var provider = new TestExportProvider();
// Create our container.
var container = new CompositionContainer(catalog, provider);
// Register the composition service to satisfy it's own imports.
provider.SetCompositionService(container);
Obviously you wouldn't be able to use any imports and your ExportProvider will explicitly create for you, but for everything else, it should work.

Trouble with Include extension on IObjectSet not working

Could anyone help me in assessing why the code below doesn't work. I'm using the common extension method for implementing Include when using IObjectset. In our repositories we were seeing this not returning correctly so I've isolated the code in test app as below. I've also included the interface based Context if this may prove relevant and a screenshot of the relevant model section. This occurs for all Includes on IObjectSet properties not just the DPASelections one I've chosen for this example.
If I update the context to return ObjectSet (still using the POCO entities) rather than IObjectSet it all works fine. When using IObjectSet and the extension method and step through the code I see that the extension method is completing correctly with a call to the ObjectQuery we're casting to but the included entities are never returned on the graph. As said, this works perfectly when I don't interface out the Context and return ObjectSet properties hence calling Include directly on ObjectSet.
I'm not getting any errors on executing the query so this isn't the same as several other questions on SO which refer to compiled queries.
Has anyone else experienced problems with this extension method implementation or can anyone spot what I'm doing wrong here?
Any help very much appreciated.
static void Main(string[] args)
{
using (var context = new AssocEntities())
{
context.ContextOptions.LazyLoadingEnabled = false;
Candidate candidate = context.Candidates
.Include("DPASelections.DPAOption")
.SingleOrDefault(c => c.Number == "N100064");
//Count is 0 when using ext. method and IObjectSet through AssocContext but correct when using Include
//on ObjectSet through AssocContext
Console.WriteLine("DPASelection count = {0}",candidate.DPASelections.Count);
//This is always null when using IObjectSet and ext. method but populated
//when using Include on ObjectSet
var option = candidate.DPASelections.First().DPAOption;
Console.WriteLine("First DPAOption = {0} : {1}",option.Id,option.Text);
}
Console.ReadLine();
}
}
public static class Extensions
{
public static IQueryable<TSource> Include<TSource>(this IQueryable<TSource> source, string path)
{
var objectQuery = source as ObjectQuery<TSource>;
if (objectQuery != null)
{
objectQuery.Include(path);
}
return source;
}
}
//Subset of custom context implementing IObjectSet as returns.
//Works fine when I return ObjectSet rather than IObjectSet and use
//the Include method directly
public partial class AssocEntities : ObjectContext
{
public const string ConnectionString = "name=AssocEntities";
public const string ContainerName = "AssocEntities";
#region Constructors
public AssocEntities()
: base(ConnectionString, ContainerName)
{
this.ContextOptions.LazyLoadingEnabled = true;
}
public AssocEntities(string connectionString)
: base(connectionString, ContainerName)
{
this.ContextOptions.LazyLoadingEnabled = true;
}
public AssocEntities(EntityConnection connection)
: base(connection, ContainerName)
{
this.ContextOptions.LazyLoadingEnabled = true;
}
#endregion
#region IObjectSet Properties
public IObjectSet<Address> Addresses
{
get { return _addresses ?? (_addresses = CreateObjectSet<Address>("Addresses")); }
}
private IObjectSet<Address> _addresses;
public IObjectSet<Answer> Answers
{
get { return _answers ?? (_answers = CreateObjectSet<Answer>("Answers")); }
}
private IObjectSet<Answer> _answers;
public IObjectSet<Candidate> Candidates
{
get { return _candidates ?? (_candidates = CreateObjectSet<Candidate>("Candidates")); }
}
}
And the model...
I needed to replace objectQuery.Include(path); with objectQuery = objectQuery.Include(path);
In .Net framework 4.0 there is a build-in Extentionmethod for Include
just add the System.Data.Entity namespace.
It uses reflection - here is how it works:
private static T CommonInclude<T>(T source, string path)
{
MethodInfo method = source.GetType().GetMethod("Include", DbExtensions.StringIncludeTypes);
if (!(method != (MethodInfo) null) || !typeof (T).IsAssignableFrom(method.ReturnType))
return source;
return (T) method.Invoke((object) source, new object[1]
{
(object) path
});
}