2

I need to pass a Context object from EF into a WCF method.

Normally, I create the Context object in the WCF method and dispose of it right before the end of the method call which works just fine for most of my methods.

However, I need to pass the Context object (specifically the DBContext) over from the MVC controller to my specific WCF method because I have caching enabled for some lookup tables. I need this specific Context object passed over (the one I set in the Application_Start method of the Global.asax file) rather than what I do in the sentence above because I use this specific object for the SqlDependency. If I try and create the DBContext object brand new, I can't use the SqlDependency becuase I will get an error informing me that the SqlDependency needs to be enabled before the database call.

The problem is that I'm getting the following error (shortened for brevity) when I try and start my WCF Test Client tool which I know has something to do with not properly declaring a KnownType attribute (ie the DBContext object). Note that the WCF project compiles just fine. I need some help with this specific part since I have never used a KnownType in my WCF service. They have all been simple types (int, string, etc).

Error: Cannot obtain Metadata from http://localhost:8732/Design_Time_Addresses/YeagerTechWcfService/YeagerTechWcfService/mex

If this is a Windows (R) Communication Foundation service to which you have access, please check that you have enabled metadata publishing at the specified address. For help enabling metadata publishing, please refer to the MSDN documentation at http://go.microsoft.com/fwlink/?LinkId=65455.WS-Metadata Exchange

Error URI: http://localhost:8732/Design_Time_Addresses/YeagerTechWcfService/YeagerTechWcfService/mex Metadata contains a reference that cannot be resolved:

I have the following OperationContract code in my WCF service:

[OperationContract]
        IEnumerable<Category> GetCategories(YeagerTechEntities DbContext);

I have the following DataContract code in my WCF service:

namespace YeagerTechModel
{
    [Serializable]
    [DataContract(IsReference = true)]
    [KnownType(typeof(YeagerTechEntities))]
    public partial class Category
    {
        public Category()
        {
            this.Projects = new HashSet<Project>();
        }

        [DataMember]
        public short CategoryID { get; set; }
        [DataMember]
        public string Description { get; set; }

        [DataMember]
        public virtual ICollection<Project> Projects { get; set; }
    }

}

Finally, the following is my WCF method:

public IEnumerable<YeagerTechModel.Category> GetCategories(YeagerTechEntities DbContext)
        {
            //YeagerTechEntities DbContext = new YeagerTechEntities();

            DbContext.Configuration.ProxyCreationEnabled = false;

            IEnumerable<YeagerTechModel.Category> category = DbContext.Categories.Where(p => p.CategoryID > 0).AsCached("Categories").ToList();
            //IEnumerable<YeagerTechModel.Category> category = DbContext.Categories.Where(p => p.CategoryID > 0);

            CloseConnection(DbContext);

            return category;
        }
Ladislav Mrnka
  • 349,807
  • 56
  • 643
  • 654
sagesky36
  • 4,362
  • 17
  • 77
  • 125
  • Does this error go away if you change your code to return `null`? How about if you also get rid of the `KnownType`? Trying to split up the code like this, removing one potential point of failure at a time, will help to isolate the problem. – Merlyn Morgan-Graham Dec 11 '11 at 06:22
  • I put the KnowType attribute in my DataContract after I got the error I posted. – sagesky36 Dec 11 '11 at 06:24
  • I don't think you should pass the context in the interface. I don't think it is going to be serializable, and will probably cause huge headaches. Have you tried removing it (possibly making the body empty while you do it)? You can pass it in using other methods, but should be doing that selection on the server side. – Merlyn Morgan-Graham Dec 11 '11 at 06:30
  • Other methods, for example Dependency Injection - http://stackoverflow.com/questions/3466886/using-ninject-wcf-extension-with-wcf-web-service – Merlyn Morgan-Graham Dec 11 '11 at 06:32

1 Answers1

1

You need singleton object following registry / service locator pattern. This object will hold reference to your global objects. For example at application start you will fill this object with your context using SqlDependency and you will use the registry to access this context in your controller's actions and service's operations.

Anyway work with this very carefully. SqlDependency and EF doesn't play nice together because it will make your context long living. Long living context is in most cases anti-pattern. Never ever use that context for anything else then loading cached data. Don't use it for data modification or loading non cached relations! Load entities as non-tracked (AsNoTracking extension method on query) in the first query and turn off proxy creation and lazy loading for that context.

Also be aware that query in EF is always executed in the database. I'm not sure what your AsCached is supposed to do but I somehow doubt it will work. What you need is probably:

var category = DbContext.Categories.Local
                        .Where(p => p.CategoryID > 0)
                        .ToList();

I would not use SqlDependency with EF. I would use ADO.NET and SQL directly. For caching in EF I would check EF Caching provider to use second level cache which is in most cases enough.

Community
  • 1
  • 1
Ladislav Mrnka
  • 349,807
  • 56
  • 643
  • 654
  • Ladislav, thanks for your comments. After reading about the EF Caching provider, it seems that this is too complex for what I want to do. In additon, for some it works, and others, it doesn't. I am simply going to wait until EF will have a caching property built into it in a later version. It's a wonder to me why MS did not think of having something like this in place since the 4.0 or 4.1 frameworks came out. Hopefully, they will implement this soon in an upcoming framework. I know NHibernate has something of a SQL Dependency cache built into it. – sagesky36 Dec 11 '11 at 18:31