Что такое сессия NHibernate.Load в Entity Framework? - PullRequest
8 голосов
/ 15 июля 2011

Что означает следующая ленивая загрузка NHibernate, эквивалентная Entity Framework?

product.Categories.Add(s.Load<Category>(cat));

Я попробовал это, но он прочитал таблицу категорий из базы данных:

product.Categories.Add(db.Categories.Find(cat));

Ответы [ 3 ]

9 голосов
/ 18 июля 2011

Эквивалента нет и, вероятно, никогда не будет из-за фундаментального недостатка конструкции в том, как EF выполняет отложенную загрузку.

Я недавно задал ваш точный вопрос на форумах MS: http://social.msdn.microsoft.com/Forums/en-US/adonetefx/thread/fccfcf68-2b53-407f-9a87-a32426db6f36

3 голосов
/ 02 апреля 2017

Вот несколько методов расширения, которые я создал для эмуляции загрузки NHibernate. Второй - для сущностей с составными ключами. Гораздо страшнее, чем первый, но он работает.

public static class EntityFrameworkExtensions
{
    // Loads when the Id property is always "Id" based on derived types of EntityBase<TId>
    public static TEntity LoadEntity<TEntity,TId>(this DbContext context, TId id) where TEntity : EntityBase<TId>, new()
    {
        var entity = context.ChangeTracker.Entries<TEntity>().SingleOrDefault(e => e.Entity.Id.Equals(id))?.Entity;

        if (entity == null)
        {
            entity = new TEntity { Id = id };
            context.Set<TEntity>().Attach(entity);
        }

        return entity;
    }

    // Loads when you're dealing with a composite key and need to specify both how to identify the key and how to assign if attaching a newly created entity.
    public static TEntity LoadEntity<TEntity>(this DbContext context, Func<TEntity, bool> predicate, Action<TEntity> idAssignmentAction) where TEntity : class, new()
    {
        var entity = context.ChangeTracker.Entries<TEntity>().SingleOrDefault(e => predicate(e.Entity))?.Entity;

        if (entity == null)
        {
            entity = new TEntity();
            idAssignmentAction(entity);
            context.Set<TEntity>().Attach(entity);
        }

        return entity;
    }
}

    // Loads by allowing you to specify an expression identifying the primary key property
    public static TEntity LoadEntity<TEntity, TIdProperty>(this DbContext context,
        Expression<Func<TEntity, TIdProperty>> idExpression, TIdProperty id) where TEntity : class, new()
    {
        var parameterExpression = Expression.Parameter(typeof(DbEntityEntry<TEntity>), "ent");
        Expression entityProperty = Expression.Property(parameterExpression, "Entity");
        var keyValue = Expression.Invoke(idExpression, entityProperty);
        var pkValue = Expression.Constant(id, typeof(TIdProperty));
        Expression equalsExpression = Expression.Equal(keyValue, pkValue);
        var lambda = Expression.Lambda<Func<DbEntityEntry<TEntity>, bool>>(equalsExpression, parameterExpression);
        var lambdaC = lambda.Compile();

        var entity = context.ChangeTracker.Entries<TEntity>().SingleOrDefault(lambdaC)?.Entity;


        if (entity == null)
        {
            entity = new TEntity();

            var valueParameterExpression = Expression.Parameter(typeof(object));
            var targetExpression = idExpression.Body is UnaryExpression
                ? ((UnaryExpression) idExpression.Body).Operand
                : idExpression.Body;

            var assign = Expression.Lambda<Action<TEntity, object>>
            (
                Expression.Assign(targetExpression,
                    Expression.Convert(valueParameterExpression, targetExpression.Type)),
                idExpression.Parameters.Single(),
                valueParameterExpression
            );

            assign.Compile().Invoke(entity, id);
            context.Set<TEntity>().Attach(entity);
        }

        return entity;
    }

Пример использования:

var account1 = _dbContext.LoadEntity<Account, int>(request.AccountId);

var account2 = _dbContext.LoadEntity<AccountWithComposite>(a => a.X == 1 && a.Y == 2, a => { a.X = 1; a.Y = 2; });

var account3 = _dbContext.LoadEntity<Account, int>(a => a.AccountId, request.AccountId);
0 голосов
/ 17 июля 2011

На данный момент эквивалента нет.

Однако вы можете попробовать это, если не внесете никаких изменений в категорию.

Entity Framework 4.0:

Category cat = new Category();
cat.Id = i;
context.Attach("Categories", cat);
product.Categories.Add(cat);

Entity Framework 4.1:

Category cat = new Category();
cat.Id = i;
context.Categories.Attach(cat);
product.Categories.Add(cat);

ссылка MSDN

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...