c# - 如何禁用泛型复杂类型字段的延迟加载?

标签 c# entity-framework generics lazy-loading

我正在使用 EF 与我的数据库进行交互。 我已经实现了一个通用存储库:

public class GenericDbRepository<TEntity> 
        : IGenericRepository<TEntity> where TEntity : class

它有这样的方法:

public virtual TEntity GetById(int id)
{
    using (MyDataContext context = new MyDataContext())
    {
       return context.Set<TEntity>().Find(id);
    }
}

还有两种模式:

public class Project
{
    public Project()
    {
        Tasks = new HashSet<Task>();
    }

    public int Id { get; set; }

    public string Name { get; set; }

    public bool Enabled { get; set; }

    public State State { get; set; }

    public DateTime? ChangeDate { get; set; }

    public virtual ICollection<Task> Tasks { get; set; }
}

public class Task
{
    public int Id { get; set; }

    public int ProjectId { get; set; }

    public string Name { get; set; }

    public int Interval { get; set; }

    public DateTime NextStart { get; set; }
}

在 MyDataContext OnModelCreating 方法中,我正在链接模型:

 modelBuilder.Entity<Project>()
            .HasMany(e => e.Tasks);

在创建 GenericDbRepository 实例并执行 GenericDbRepository(someId) 时一切正常。

但如果 TEntity 具有复杂类型字段(在我的例子中是 ICollection Tasks),则会出现异常“ObjectContext 实例已被处理,不能再用于需要连接的操作”。

我知道 MyDataContext 在 GetById 方法返回值后被处理,之后任务不可用。

我尝试这样做:

public MyDataContext()
    : base("name=MyDataContext") 
{
    this.Configuration.LazyLoadingEnabled = false;
}

它对描述的问题有很大帮助,但会产生另一个问题:Tasks not linking to Project and I'm always get empty Tasks field.所以,这不是一个选择。

因此,问题是如何在上下文处理之前获取如此复杂的类型字段值。

最佳答案

您的导航属性导致错误的原因是您在加载导航属性之前处理了上下文。

为避免此类错误,您可以在通用存储库中使用 Include 方法为您的 Project 加载 Tasks,例如,你可以这样做:

 public virtual T FindElement(Func<T, bool> where, params Expression<Func<T, object>>[] navigationProperties)
 {
        T item = null;
        using (var context = new Entities())
        {
            IQueryable<T> dbQuery = context.Set<T>();

            //Apply eager loading
            foreach (Expression<Func<T, object>> navigationProperty in navigationProperties)
                dbQuery = dbQuery.Include<T, object>(navigationProperty);

            item = dbQuery
                  .FirstOrDefault(where); //Apply where clause
        }
        return item;
 }

使用此方法,您可以找到应用多个包含的元素,在您的情况下,可能是这样的:

var repository=new GenericDbRepository<Project>();
var project=repository.FindElement(p=>p.Id==23, p=>p.Tasks, p=>p.State);

关于c# - 如何禁用泛型复杂类型字段的延迟加载?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28585089/

相关文章:

c# - Excel 2003 中没有 XlFileFormat.xlOpenXMLWorkbook 支持是否有任何解决方法?

c# - 为什么我们需要在 C# 中锁定和对象?

c# - 在 Web 服务中读取和重写 HttpResponse

c# - 负载测试期间观察到套接字异常

sql - Entity Framework - 如何过滤预先加载的导航/关系属性?

sql-server - SQL Server - JOIN 未在 Entity Framework 生成的查询中使用最佳顺序

java - 强制两个参数化类型不同java

java - "... unchecked or unsafe operations"通用容器类

c# - 是否可以在 Visual Studio Express 版本中将 Entity Framework 与 MySQL 一起使用?

c# - 通过 MVVM Light RelayCommand 绑定(bind)泛型类型