4

我有实体框架 4.1 的小问题。

有图像DTO接口:

public interface IImage : IDtoBase
{
    string FullFilePath { get; set; }
    int Width { get; set; }
    int Heigth { get; set; }
    long ImageTypeId { get; set; }
    IImageType Type { get; set; }
}

有配置上下文的代码:

// where TContext : DbContext, new()
private TInterface Invoke(Func<TContext, TInterface> callback)
{
    using (var context = new TContext())
    {
        context.Configuration.AutoDetectChangesEnabled = true;
        context.Configuration.LazyLoadingEnabled = true;
        context.Configuration.ProxyCreationEnabled = true;
        context.Configuration.ValidateOnSaveEnabled = true;

        context.Database.Connection.Open();

        return callback.Invoke(context);
    }
}

有代码可以获取所需的 DTO 项目:

public TInterface Get(long id)
{
    return Invoke(
        context =>
        {
            TDto dto = context.Set<TDto>().FirstOrDefault(x => (x.Id == id));
            return dto.Convert<TDto, TInterface>();
        }
    );
}

如果我设置context.Configuration.LazyLoadingEnabled = false,则图像 DTO 的“类型”属性为空(我认为,没关系)。

如果context.Configuration.LazyLoadingEnabled具有“true”值,则图像 DTO 的“Type”属性在“using”语句中具有正确的值,但该属性在处置上下文后处置 - “ObjectContext 实例已处置,不能再用于操作需要连接。”

即图像 DTO 存在/未处置,但其“类型”属性已处置。

任何人都可以提供任何解决方案 - 不要处置“类型”属性(我想使用“使用”语句而不是“处置”模式)?

4

1 回答 1

4

首先,您需要了解延迟加载的工作原理。EF 通过创建从您的实体类继承的代理并覆盖导航属性访问行为来做到这一点。当您第一次访问导航属性时,如果在代理类有逻辑通过context加载它之前没有加载它。因此代理实例保持对上下文的引用。

当执行离开您的Invoke方法时,上下文将被释放。因此代理不能延迟加载导航属性。你可以做几件事来解决这个问题。

  • 急切加载导航属性

使用Include急切加载的方法

public TInterface Get(long id)
{
    return Invoke(
        context =>
        {
            TDto dto = context.Set<TDto>().Include(t => t.Type)
                  .FirstOrDefault(x => (x.Id == id));

            return dto.Convert<TDto, TInterface>();
        }
    );
}
  • 控制上下文的生命周期 如果不立即在Invoke方法内释放上下文,您可以使用现有的上下文实例,该实例将在您完成数据访问后释放。这可以通过 IoC/DI 框架来完成。对于 Web 项目,生命周期通常仅限于单个请求。
于 2012-06-12T00:05:50.407 回答