Службы данных WCF / Entity Framework: регистрация имени пользователя клиента, аутентификация, авторизация - PullRequest
3 голосов
/ 17 июля 2011

Я использую Entity Framework со службами данных WCF, и в моей базе данных есть следующая таблица:

Таблица контрактов

  • Id (int)
  • Имя(varchar)
  • byUser (varchar)
  • isDeleted (бит)

Класс Entity Framework

  • Id (int)
  • Имя (строка)
  • byUser (строка)
  • isDeleted (логическое значение)

всякий раз, когда пользователь вставляет / обновляет / удаляет контракт (черезклиентское приложение), мне нужно зарегистрировать, кто выполнил действие.

, поэтому я создал хранимые процедуры для вставки / обновления / удаления, которые будут получать имя пользователя от клиента при выполнении вставки / удаления / обновления.

проблема в том, что операция удаления не отправляет тому, кто выполняет операцию:

        var ctx = Context;
        var contractToDelete = ctx.Contracts.Where(c => c.ContractId == 1).First();
        contractToDelete.ByUser = username;
        ctx.DeleteObject(contractToDelete);
        ctx.SaveChanges();

на стороне сервера, byUser всегда равен нулю.

Вопросы:

1) Как сделать так, чтобы параметр byUser отправлялся на сервер?

2) Есть лилучший способ справиться с этим сценарием?(регистрация / аутентификация / авторизация) с Entity Framework

Ответы [ 2 ]

2 голосов
/ 17 июля 2011

Не отправляет ноль "всегда". Он отправляет старое значение всегда. Это некоторая внутренняя логика в рамках сущности. Для каждого отслеживаемого объекта EF сохраняет как исходные, так и текущие значения. Когда вы удаляете объект, EF не использует текущие значения - он использует оригинальные значения (не спрашивайте меня, почему, просто так это работает).

Так что нужно обмануть EF:

var ctx = Context;
var contractToDelete = ctx.Contracts.Where(c => c.ContractId == 1).First();
contractToDelete.ByUser = username;
ctx.Contracts.ApplyOriginalValues(contractToDelete);
ctx.DeleteObject(contractToDelete);
ctx.SaveChanges();

Вызов ApplyOriginalValues заставит EF переопределить исходные значения значениями, переданными в параметре = вы переопределите исходные значения текущими значениями.

По моему мнению, лучший способ - хранить удаленные записи в отдельной таблице, потому что это позволит избежать многих проблем с передачей isDeleted=false на каждый запрос, где как быстрая, так и отложенная загрузка также загрузит удаленные записи. Единственный способ избежать проблем с isDeleted - это использование условного отображения, но в этом случае вы не сможете загружать удаленные записи, даже если захотите, если не используете хранимые процедуры или прямые запросы SQL.

1 голос
/ 17 июля 2011

То, как мне это удалось, - когда мой пользователь входит в систему, я сохраняю основную информацию о нем в сеансе.Затем у меня есть класс, который стоит поверх моих действий в контексте.

Всякий раз, когда я фиксирую изменения, я выполняю ту же процедуру, которая проверяет, что изменилось.Я разработал способность инициировать действия, основанные на объекте, с которым работаем (так что я могу следить за чем-то вроде контрактов).Тогда у меня есть пользователь, который может войти в систему.

[Редактировать]

Это сложнее, чем я понял, но я попробую.

Я создаю веб-приложение.Тяжело используя Ninject.

Когда пользователь входит в систему, я сохраняю его информацию в объекте IUserSession (это действительно хранится в Session, но пользовательская область Ninject делает это аккуратным для меня и не дает мне возможности выставлять своислой данных для веб-сессии).Этот объект сеанса пользователя содержит имя пользователя, идентификатор пользователя и т. Д.

Я создал класс, который содержит контекст и упаковывает все вызовы SELECT, CREATE, DELETE и COMMIT.т.е. SELECT;

public IQueryable<TEntity> All<TEntity>( ) {
  return Context.Set<TEntity>();
}

Этот класс также имеет метод Commit, это вызов SaveChanges.

Перед вызовом SaveChanges у вас есть доступ к изменениям в форме Context.ChangeTracker..Entities

Для каждой измененной сущности вы можете проверить, была ли она добавлена, удалена или изменена. Чтобы получить тип изменяемого элемента;

Type baseEntityType = ObjectContext.GetObjectType( entity.Entity.GetType( ) );

Я делаюпланирую написать учебник в ближайшее время, основываясь на моем личном опыте с этим (не то, что вам сейчас помогает).

...