将实体框架上下文对象传递给WCF

时间:2011-12-11 06:19:58

标签: wcf entity-framework-4.1

我需要将一个Context对象从EF传递给WCF方法。

通常,我在WCF方法中创建Context对象并在方法调用结束之前处理它,这对我的大多数方法都很好。

但是,我需要将Context对象(特别是DBContext)从MVC控制器传递到我的特定WCF方法,因为我为某些查找表启用了缓存。我需要传递这个特定的Context对象(我在Global.asax文件的Application_Start方法中设置的对象),而不是我在上面的句子中所做的,因为我将此特定对象用于SqlDependency。如果我尝试创建全新的DBContext对象,我不能使用SqlDependency,因为我会收到错误通知我在数据库调用之前需要启用SqlDependency。

问题是当我尝试启动我的WCF测试客户端工具时,我遇到了以下错误(简洁起见),我知道这与未正确声明KnownType属性(即DBContext对象)有关。请注意,WCF项目编译得很好。我需要一些特定部分的帮助,因为我从未在WCF服务中使用过KnownType。它们都是简单的类型(int,string等)。

  

错误:无法从http://localhost:8732/Design_Time_Addresses/YeagerTechWcfService/YeagerTechWcfService/mex

获取元数据      

如果这是您的Windows(R)Communication Foundation服务   有权访问,请检查您是否已启用元数据发布   指定的地址。有关启用元数据发布的帮助,请   请参阅MSDN文档   http://go.microsoft.com/fwlink/?LinkId=65455.WS-Metadata交换

     

错误URI:   http://localhost:8732/Design_Time_Addresses/YeagerTechWcfService/YeagerTechWcfService/mex   元数据包含无法解析的引用:

我的WCF服务中有以下OperationContract代码:

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

我的WCF服务中有以下DataContract代码:

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; }
    }

}

最后,以下是我的WCF方法:

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;
        }

1 个答案:

答案 0 :(得分:1)

您需要在注册表/服务定位器模式之后使用单个对象。此对象将保留对全局对象的引用。例如,在应用程序启动时,您将使用SqlDependency使用您的上下文填充此对象,并且您将使用注册表在控制器的操作和服务操作中访问此上下文。

无论如何都非常谨慎地使用它。 SqlDependency和EF不能很好地融合在一起,因为它会使你的语境长久存在。长期生活环境为in most cases anti-pattern。除了加载缓存数据之外,永远不要使用该上下文。不要将它用于数据修改或加载非缓存关系!在第一个查询中将实体加载为非跟踪(AsNoTracking查询扩展方法),并关闭该上下文的代理创建和延迟加载。

另请注意,EF中的查询始终在数据库中执行。我不确定你的AsCached应该做什么,但我不知道它会起作用。你需要的可能是:

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

我不会将SqlDependency用于EF。我会直接使用ADO.NET和SQL。对于EF中的缓存,我会检查EF Caching provider以使用二级缓存,这在大多数情况下都足够了。