2010-09-27 25 views
9

Veritabanım, giriş yapan kullanıcıyı bir değişiklik yapan bir uygulamadan almayı planladığım her tabloda 'LastModifiedUser' sütununa sahiptir. Ben veritabanı kullanıcısı hakkında konuşmuyorum, bu yüzden aslında bu her varlıktaki bir dizedir. Bunu, her varlık için varsayılan olarak belirlemenin bir yolunu bulmak isterim, böylece diğer geliştiriciler, varlıkları oluşturdukları zaman atamayı hatırlamak zorunda kalmazlar.Entity Framework - Denetleme faaliyeti

Yani böyle bir şey gerçekleşir:

using (EntityContext ctx = new EntityContext()) 
{ 
    MyEntity foo = new MyEntity(); 

    // Trying to avoid having the following line every time 
    // a new entity is created/added. 
    foo.LastModifiedUser = Lookupuser(); 

    ctx.Foos.Addobject(foo); 
    ctx.SaveChanges(); 
} 

cevap

23

ObjectStateManager

İlk yararlanarak EF 4.0 Bunu gerçekleştirmek için mükemmel bir yol yoktur, kendi ObjectContext için kısmi bir sınıf oluşturmak ve abone olmanız gerekir ObjectContext.SavingChanges Event. Bu etkinliğe abone olmak için en iyi yer, OnContextCreated Yöntemin içinde. Şimdi

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


iş yapacak gerçek kod:

void Context_SavingChanges(object sender, EventArgs e) { 

    IEnumerable<ObjectStateEntry> objectStateEntries = 
     from ose 
     in this.ObjectStateManager.GetObjectStateEntries(EntityState.Added 
                 | EntityState.Modified) 
     where ose.Entity != null 
     select ose; 

    foreach (ObjectStateEntry entry in objectStateEntries) { 

     ReadOnlyCollection<FieldMetadata> fieldsMetaData = entry.CurrentValues 
       .DataRecordInfo.FieldMetadata; 

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

     if (modifiedField.FieldType != null) { 

      string fieldTypeName = modifiedField.FieldType.TypeUsage.EdmType.Name;      
      if (fieldTypeName == PrimitiveTypeKind.String.ToString()) { 
       entry.CurrentValues.SetString(modifiedField.Ordinal, Lookupuser()); 
      } 
     } 
    } 
} 

Kod Bu yöntem bağlam nesnenin yapıcı ve hiçbir uygulanması ile kısmi yöntemdir yapıcı aşırı tarafından çağrılan Açıklama:
Bu kod şu anda sahip herhangi bir Eklendi veya Değiştirilmiş LastModifiedUser özelliğine sahip olan ve daha sonra bu özel mülkünüzü özel Lookupuser() yönteminden gelen değerle güncelleştirengirdiler. foreach bloğunda

, sorgu temel olarak her giriş CurrentValues içine deler. Ardından yöntemi kullanılarak, bu toplayıp, söz konusu girişin her FieldMetaData öğenin adına bakar sadece bu kimin NameLastModifiedUserolduğunu. Sonra, if deyimi, LastModifiedUser özelliğinin Dize alanı olduğunu doğrular; daha sonra alanın değerini günceller.

(yerine SavingChanges olay için abone), bu yöntem bağlamak için başka bir yolu ObjectContext.SaveChanges Method geçersiz gereğidir. Bu arada

, yukarıdaki kod onu Programming Entity Framework kitaptan Julie Lerman aittir.Öz İzleme POCO Uygulanması İçin


DÜZENLEME: Eğer kendi kendine izleme Poços varsa

sonra ne yapacağını ben ilk OnContextCreated() yöntemini çağırmak için T4 şablonunu değiştirmek olmasıdır. ObjectContext.tt dosyanıza bakarsanız, tüm kurucular tarafından çağrılan bir Initialize() yöntemi vardır, bu nedenle OnContextCreated() yöntemimizi çağırmak için iyi bir adaydır, bu nedenle tek yapmamız gereken ObjectContext.tt dosyasını değiştirmektir.

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); 
    // We call our custom method here: 
    OnContextCreated(); 
} 

Ve bu() Bağlamında oluşturulması üzerine çağrılacak bizim OnContextCreated neden olur: Bunun gibi dosya. Eğer servis sınırı arkasına Poços koyarsanız

Şimdi, o zaman ModifiedUserName WCF hizmeti tüketicisi gelen verilerin geri kalanı ile gelmelidir demektir. Sen güncellemek için onlara bu LastModifiedUser özelliği maruz bırakabilir ya da başka bir özelliğinde saklar ve bu özelliğinden LastModifiedUser güncellemek istiyorsanız aşağıdaki gibi, o zaman 2 kodunu değiştirebilirsiniz:


foreach (ObjectStateEntry entry in objectStateEntries) { 

    ReadOnlyCollection fieldsMetaData = entry.CurrentValues 
      .DataRecordInfo.FieldMetadata; 

    FieldMetadata sourceField = fieldsMetaData 
      .Where(f => f.FieldType.Name == "YourPropertyName").FirstOrDefault();    

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

    if (modifiedField.FieldType != null) { 

     string fieldTypeName = modifiedField.FieldType.TypeUsage.EdmType.Name; 
     if (fieldTypeName == PrimitiveTypeKind.String.ToString()) { 
      entry.CurrentValues.SetString(modifiedField.Ordinal, 
        entry.CurrentValues[sourceField.Ordinal].ToString()); 
     } 
    } 
} 


Bu yardımcı olur umarım.

+0

teşekkürler. Daha önce bu desene bakmıştım ama onContextCreated olayını asla ateş edemedim. – Biggle10

+1

Sorun değil. Söylediğim gibi, OnContextCreated bir Etkinlik değildir, yalnızca bağlam nesnesinin yapıcısı ve yapıcı aşırı yüklenmeleri tarafından çağrılan hiçbir uygulama olmayan kısmi bir yöntemdir. Yapmanız gereken tek şey, içeriğiniz için kısmi bir sınıf oluşturmak ve 1. kod snippet'imi içine koymaktır. Lütfen bunu yapın ve sizin için nasıl çalıştığını bana bildirin, eğer hala çalışmıyorsa, işe yaratacağız! –

+0

Aslında bunu yanlış yöne düşünüyordum ve yanlış anladım. Sorumu düzeltmeme izin verin ... Kendi kendine trackign varlıkları kullanıyoruz ve bir WCF servisi ile ön tarafa servis ediliyoruz. Geri döndüklerinde, yeniden bağlamlara geçip kaydederiz. İstemciye sahipken değiştirildiyse, lastModifiedUser bunu yansıtmalıdır. Sunucu, currentUser'ın kim olduğunu bilmek için erişim hakkına sahip değildir, bu nedenle kullanıcıyı ayarlamaktan sorumlu kişi olamaz. Teorik olarak, varlık düzeyinde bir olay/kısmi yöntem gibi bir şey yapmak istediğimi varsayalım? – Biggle10