在“使用”声明后不要处置财产

时间:2012-06-11 21:58:01

标签: c# .net entity-framework entity-framework-4.1 dispose

我有一个小问题,实体框架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存在/未被处理,但其“类型”属性已被处理。

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

1 个答案:

答案 0 :(得分:4)

首先,您需要了解延迟加载的工作原理。 EF通过创建从您的实体类继承的代理来完成此操作,并覆盖导航属性访问行为。首次访问导航属性时,如果在代理类具有通过上下文加载它的逻辑之前未加载它。因此代理实例保留对上下文的引用。

当执行离开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项目,生命周期通常仅限于一个请求。