Могу ли я сначала использовать строго типизированные POCO в качестве связанных значений с кодом EF, не создавая каждый раз новые? - PullRequest
3 голосов
/ 27 июля 2011

У меня есть поле состояния для класса, который имеет идентификатор и имя.Я не использую enum для его моделирования, а скорее класс с некоторыми статическими значениями, например:

    public class MailoutStatus : IEntity
{
    public static MailoutStatus Draft = new MailoutStatus() { Id = 1, Name = "Draft" };
    public static MailoutStatus Scheduled = new MailoutStatus() { Id = 2, Name = "Scheduled" };
    public static MailoutStatus Cancelled = new MailoutStatus() { Id = 3, Name = "Cancelled" };
    public static MailoutStatus Sent = new MailoutStatus() { Id = 4, Name = "Sent" };

    public int Id { get; set; }
    public string Name { get; set; }
...
}

Теперь я хочу установить это значение состояния для описываемого объекта, например, так:

        var repo = new MailoutRepository();
        var mailout = repo.Get(1);
        mailout.Status = MailoutStatus.Cancelled;
        repo.Update(mailout);
        repo.CommitChanges();

Однако этот код будет видеть MailoutStatus.Cancelled как новый объект и вставит новую строку в таблицу MailoutStatus, игнорируя идентификатор, который уже включен, и добавив новый идентификатор, созданный IDENTITY (например,5).Я могу предотвратить это, добавив объект проверки сущности, но это только приводит к тому, что вышеперечисленное взрывается из-за ошибки проверки.

Я могу обойти проблему, используя этот код:

    var repo = new MailoutRepository();
    var mailout = repo.Get(1);
    mailout.Status = new MailoutStatusRepository().Get(MailoutStatus.Cancelled.Id);
    repo.Update(mailout);
    repo.CommitChanges();

Этоработает, потому что теперь Entity Framework знает о MailoutStatus, который я извлекаю, и отслеживает его состояние и т. д. Но действительно глупо писать столько кода просто для установки статуса.Я также не хочу использовать enum по другим причинам, и я не хочу, чтобы MailoutStatus что-то знал о постоянстве.Есть идеи?

Ответы [ 3 ]

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

Вы уже дублируете то, что находится в базе данных. Если вы изменили свою модель, теперь она имеет только целочисленный статус, тогда вы можете изменить MailoutStatus на статический int, и он будет работать.

Другими словами, что вы получаете, имея MailoutStatus в качестве другой сущности, когда на самом деле это просто значение поиска?

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

Вот как я это решил.

Я определил атрибут с именем NotTrackedAttribute и применил его к сущностям типа Status. Затем переопределите метод SaveChanges производного контекста следующим образом. Сброс отслеживаемых изменений для этих объектов

    public override int SaveChanges()
    {
        var changedEntities = ChangeTracker.Entries();

        foreach (var changedEntity in changedEntities)
        {
             var entity = changedEntity.Entity;

             //ignore the types that are marked as NotTracked
             if (Attribute.IsDefined(entity.GetType(), typeof(NotTrackedAttribute)))
             {
                 changedEntity.State = EntityState.Unchanged;
                 continue;
             }
        }

        return base.SaveChanges();
    }

Атрибут

/// <summary>
/// Indicates that a Type having this attribute should not be persisted.
/// </summary>
[AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = true)]
public class NotTrackedAttribute : Attribute
{
}

Затем используйте его следующим образом

[NotTracked]
public class MailoutStatus
{

}
0 голосов
/ 27 июля 2011

Теперь EF поддерживает перечисления.http://blogs.msdn.com/b/efdesign/archive/2011/06/29/enumeration-support-in-entity-framework.aspx. В первом коде вы можете использовать столбец дискриминатора для отображения перечисления.Или же это хорошее решение Перечисляет сначала EF code - стандартный метод для заполнения базы данных, а затем с помощью?

...