Entity Framework 4 Изменения в сохранении пользовательской логики - PullRequest
2 голосов
/ 26 апреля 2011

Я пытаюсь добавить некоторую собственную логику к своим сущностям. У каждой сущности есть свойство CreatedBy & LastUpdatedBy.

Я добавил приведенный ниже код, который отлично работает, если я добавляю, например, Человек и его адрес на ходу.

Однако, если я добавлю Person и вызову context.SaveChanges (), то добавлю их Адрес и вызову context.SaveChanges (). Код выполняется, но значение «entry» равно null, и поэтому CreatedBy & LastUpdatedBy не заполняются.

CustomRepository.CurrentUser просто получает имя пользователя.

ObjectSet = context.CreateObjectSet<TEntity>();

BusinessEntities.Person person = new BusinessEntities.Person()
{
    TitleRef = 123,
    FirstName = "FirstName",
    Surname = "Surname",
    PhoneNumber = "PhoneNumber",
    MobileNumber = "MobileNumber",
    EmailAddress = "EmailAddress",
};


ObjectSet.AddObject(entity);

Context.SaveChanges();

PersonAddress personAddress = new BusinessEntities.PersonAddress
{
    StartDate = DateTime.Now,
    EndDate = DateTime.Now,
    OtherResidents = "OtherResidents",
    CurrentAddress = true,
    Address = new Address
    {
        Address1 = "Address1",
        Address2 = "Address2",
        Address3 = "Address3"
    }
};

Context.SaveChanges();


public override int SaveChanges(SaveOptions options)
{
    foreach (ObjectStateEntry entry in
        ObjectStateManager.GetObjectStateEntries(
        EntityState.Added | EntityState.Modified))
    {
        System.Collections.ObjectModel.ReadOnlyCollection<FieldMetadata> fieldsMetaData = entry.CurrentValues
                              .DataRecordInfo.FieldMetadata;

        FieldMetadata createdField = fieldsMetaData
        .Where(f => f.FieldType.Name == "CreatedBy").FirstOrDefault();

        FieldMetadata modifiedField = fieldsMetaData
        .Where(f => f.FieldType.Name == "LastUpdatedBy").FirstOrDefault();

        if (modifiedField.FieldType != null)
        {
            string fieldTypeName = modifiedField.FieldType.TypeUsage.EdmType.Name;
            if (fieldTypeName == PrimitiveTypeKind.String.ToString())
            {
                if (entry.CurrentValues[createdField.Ordinal].ToString() == null ||
                   entry.CurrentValues[createdField.Ordinal].ToString() == String.Empty)
                {
                    entry.CurrentValues.SetString(createdField.Ordinal, CustomRepository.CurrentUser);
                }

                entry.CurrentValues.SetString(modifiedField.Ordinal, CustomRepository.CurrentUser);
            }
        }
    }
    return base.SaveChanges(options);
}

------------------------ Оригинальный метод --------------------- --------

private void Initialize()
{
    // Creating proxies requires the use of the ProxyDataContractResolver and
    // may allow lazy loading which can expand the loaded graph during serialization.
    ContextOptions.ProxyCreationEnabled = false;
    ObjectMaterialized += new ObjectMaterializedEventHandler(HandleObjectMaterialized);

    OnContextCreated(); 
}

private void OnContextCreated() 
{     
    this.SavingChanges += Context_SavingChanges; 
} 

private void Context_SavingChanges(object sender, EventArgs e) 
{
    try
    {
        IEnumerable<ObjectStateEntry> objectStateEntries =
        from ose
        in this.ObjectStateManager.GetObjectStateEntries(EntityState.Added
                                                            | EntityState.Modified)
        where ose.Entity != null
        select ose;

        foreach (ObjectStateEntry entry in objectStateEntries)
        {
            System.Collections.ObjectModel.ReadOnlyCollection<FieldMetadata> fieldsMetaData = entry.CurrentValues
                .DataRecordInfo.FieldMetadata;

            FieldMetadata createdField = fieldsMetaData
            .Where(f => f.FieldType.Name == "CreatedBy").FirstOrDefault();

            FieldMetadata modifiedField = fieldsMetaData
            .Where(f => f.FieldType.Name == "LastUpdatedBy").FirstOrDefault();

            if (modifiedField.FieldType != null)
            {
                string fieldTypeName = modifiedField.FieldType.TypeUsage.EdmType.Name;
                if (fieldTypeName == PrimitiveTypeKind.String.ToString())
                {
                    if (entry.CurrentValues[createdField.Ordinal].ToString() == null ||
                       entry.CurrentValues[createdField.Ordinal].ToString() == String.Empty)
                    {
                        entry.CurrentValues.SetString(createdField.Ordinal, CustomRepository.CurrentUser);
                    }

                    entry.CurrentValues.SetString(modifiedField.Ordinal, CustomRepository.CurrentUser);
                }
            }
        }
    }
}

Ответы [ 2 ]

2 голосов
/ 12 мая 2011

Я в итоге получил ответ.Мне нужно было вызвать Context.DetectChanges () перед сохранением (), иначе изменения не были обнаружены.

0 голосов
/ 27 апреля 2011

Вы, вероятно, должны обрабатывать событие SavingChanges вместо переопределения метода.

Кроме того, почему бы не заставить ваши объекты наследовать от базового класса или реализовать интерфейс, а не использовать отражение?Вы можете сделать это в шаблоне T4, если вы сначала используете модель / базу данных, или напрямую, если вы сначала используете код, и это даст вам лучший результат в долгосрочной перспективе, чем отражение.Затем вы также можете написать универсальные фильтры для поиска сущностей, измененных в диапазоне дат, потому что вы можете работать с вашим интерфейсом.

Я использую ObjectStateManager.GetObjectStateEntries(EntityState.Modified).OfType(Of T) (или любое состояние, которое я хочу, для любого типа сущности, который я хочу) -это позволяет мне работать против фактической сущности, а не ObjectStateEntry.

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