无需数据库调用即可获取持久实体引用

发布于 2024-10-15 18:27:48 字数 97 浏览 3 评论 0原文

是否可以获取对 id 已知的已持久对象的引用,无需数据库往返,就像使用 ISession.Load(id) 对 NHibernate 所做的那样?

Is it possible to get a reference to an already persistent object for which the id is known without a DB roundtrip, like one would do with NHibernate using ISession.Load(id)?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

醉南桥 2024-10-22 18:27:48

是的,如果对象已经加载,这是可能的。在 EF Future CTP5 的情况下,您可以使用 DbSet 实例的新 Local 属性:

var entity = context.MySet.Local.SingleOrDefault(e => e.Id == id);

ObjectContext 的情况下,情况有点小复杂 - 您需要 EntityKey 实例,在使用 POCO 时获取该实例很麻烦。

我的存储库代码的一部分:

public class Repository<TEntity> : IRepository<TEntity> where TEntity : class, IEntity
{
    private readonly EntitySetBase _entitySet;
    private readonly string _entitySetName;

    protected BaseObjectContext Context { get; set; }
    protected ObjectSet<TEntity> ObjectSet { get; set; }

    public Repository(BaseObjectContext context)
    {
        if (context == null)
        {
            throw new ArgumentNullException("context");
        }


        Context = context;
        ObjectSet = context.CreateObjectSet<TEntity>();

        var container = Context.MetadataWorkspace
            .GetEntityContainer(Context.DefaultContainerName, DataSpace.CSpace);
        _entitySet = container.BaseEntitySets
            .Single(es => es.ElementType.Name == typeof (TEntity).Name);
        _entitySetName = Context.DefaultContainerName + "." + _entitySet.Name;
    }

    public virtual IQueryable<TEntity> GetQuery()
    {
        return ObjectSet;
    }

    public virtual TEntity GetById(long id)
    {
        TEntity entity = TryGetLocalEntity(id);

        if (entity == null)
        {
            entity = GetQuery().SingleOrDefault(o => o.Id == id);
        }

        return entity;
    }

    private TEntity TryGetLocalEntity(long id)
    {
        if (_entitySet == null)
        {
            return null;
        }

        var key = new EntityKey(_entitySetName, "Id", id);
        ObjectStateEntry entry;

        if (Context.ObjectStateManager.TryGetObjectStateEntry(key, out entry))
        {
            return (TEntity) entry.Entity;
        }

        return null;
    }
}

如果未加载实例,则在不查询数据库的情况下根本无法获取引用。您可以使用虚拟对象创建。

CTP5 示例:

var entity = new MyEntity { Id = id };
context.MySet.Attach(entity);

纯 EF4 示例:

var entity = new MyEntity { Id = id };
context.Attach(entity);

或创建代理的虚拟对象(CTP5 示例):

CTP5 示例:

var entity = context.MySet.Create();
enity.Id = id;

纯 EF4 示例:

var entity = context.CreateObject<MyEntity>();
entity.Id = id;

Yes it is possible if the object is already loaded. In case of EF Future CTP5 you can use new Local property of the DbSet<T> instance:

var entity = context.MySet.Local.SingleOrDefault(e => e.Id == id);

In case of ObjectContext the situation is little bit complicated - you need EntityKey instance which is cumbersome to get when working with POCOs.

Part of my repository code:

public class Repository<TEntity> : IRepository<TEntity> where TEntity : class, IEntity
{
    private readonly EntitySetBase _entitySet;
    private readonly string _entitySetName;

    protected BaseObjectContext Context { get; set; }
    protected ObjectSet<TEntity> ObjectSet { get; set; }

    public Repository(BaseObjectContext context)
    {
        if (context == null)
        {
            throw new ArgumentNullException("context");
        }


        Context = context;
        ObjectSet = context.CreateObjectSet<TEntity>();

        var container = Context.MetadataWorkspace
            .GetEntityContainer(Context.DefaultContainerName, DataSpace.CSpace);
        _entitySet = container.BaseEntitySets
            .Single(es => es.ElementType.Name == typeof (TEntity).Name);
        _entitySetName = Context.DefaultContainerName + "." + _entitySet.Name;
    }

    public virtual IQueryable<TEntity> GetQuery()
    {
        return ObjectSet;
    }

    public virtual TEntity GetById(long id)
    {
        TEntity entity = TryGetLocalEntity(id);

        if (entity == null)
        {
            entity = GetQuery().SingleOrDefault(o => o.Id == id);
        }

        return entity;
    }

    private TEntity TryGetLocalEntity(long id)
    {
        if (_entitySet == null)
        {
            return null;
        }

        var key = new EntityKey(_entitySetName, "Id", id);
        ObjectStateEntry entry;

        if (Context.ObjectStateManager.TryGetObjectStateEntry(key, out entry))
        {
            return (TEntity) entry.Entity;
        }

        return null;
    }
}

If the instance is not loaded you simply can't get the reference without querying DB. You can use dummy object creation.

CTP5 example:

var entity = new MyEntity { Id = id };
context.MySet.Attach(entity);

Pure EF4 example:

var entity = new MyEntity { Id = id };
context.Attach(entity);

or dummy object with proxy creation (CTP5 example):

CTP5 example:

var entity = context.MySet.Create();
enity.Id = id;

Pure EF4 example:

var entity = context.CreateObject<MyEntity>();
entity.Id = id;
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文