Aracılığıyla paylaş


Özellik değerleriyle çalışma

Çoğunlukla Entity Framework, varlık örneklerinizin özelliklerinin durumunu, özgün değerlerini ve geçerli değerlerini izlemeyi üstlenir. Ancak, EF'nin özellikler hakkında sahip olduğu bilgileri görüntülemek veya değiştirmek istediğiniz bazı durumlar (örneğin, bağlantısız senaryolar) olabilir. Bu konu başlığında gösterilen teknikler, gerek Code First gerekse EF Designer ile oluşturulan modellere için geçerlidir.

Entity Framework izlenen varlığın her özelliği için iki değeri izler. Geçerli değer, adından da belirtildiği gibi varlıktaki özelliğin geçerli değeridir. Özgün değer, varlık veritabanından sorgulandığında veya bağlama eklendiğinde özelliğin sahip olduğu değerdir.

Özellik değerleriyle çalışmak için iki genel mekanizma vardır:

  • Tek bir özelliğin değeri, Property yöntemi kullanılarak kesin olarak türlenmiş bir şekilde elde edilebilir.
  • Bir varlığın tüm özellikleri için değerler DbPropertyValues nesnesine okunabilir. DbPropertyValues daha sonra özellik değerlerinin okunmasına ve ayarlanmasına izin vermek için sözlük benzeri bir nesne işlevi görür. DbPropertyValues nesnesindeki değerler, başka bir DbPropertyValues nesnesindeki değerlerden veya varlığın başka bir kopyası veya basit bir veri aktarım nesnesi (DTO) gibi başka bir nesnedeki değerlerden ayarlanabilir.

Aşağıdaki bölümlerde yukarıdaki mekanizmaların her ikisini de kullanma örnekleri gösterilmektedir.

Tek bir özelliğin geçerli veya özgün değerini alma ve ayarlama

Aşağıdaki örnekte, bir özelliğin geçerli değerinin nasıl okunabileceği ve ardından yeni bir değere nasıl ayarlanacağı gösterilmektedir:

using (var context = new BloggingContext())
{
    var blog = context.Blogs.Find(3);

    // Read the current value of the Name property
    string currentName1 = context.Entry(blog).Property(u => u.Name).CurrentValue;

    // Set the Name property to a new value
    context.Entry(blog).Property(u => u.Name).CurrentValue = "My Fancy Blog";

    // Read the current value of the Name property using a string for the property name
    object currentName2 = context.Entry(blog).Property("Name").CurrentValue;

    // Set the Name property to a new value using a string for the property name
    context.Entry(blog).Property("Name").CurrentValue = "My Boring Blog";
}

Özgün değeri okumak veya ayarlamak için CurrentValue özelliği yerine OriginalValue özelliğini kullanın.

Özellik adını belirtmek için bir dize kullanıldığında döndürülen değerin "object" olarak yazıldığını unutmayın. Öte yandan, bir lambda ifadesi kullanılırsa döndürülen değer kesin olarak yazılır.

Özellik değerinin bu şekilde ayarlanması, özelliği yalnızca yeni değer eski değerden farklıysa değiştirilmiş olarak işaretler.

Bir özellik değeri bu şekilde ayarlandığında, AutoDetectChanges kapalı olsa bile değişiklik otomatik olarak algılanır.

Eşlenmemiş bir özelliğin geçerli değerini alma ve ayarlama

Veritabanına eşlenmeyen bir özelliğin geçerli değeri de okunabilir. Eşlenmemiş bir özelliğe örnek olarak Blog'da rssLink özelliği yer alabilir. Bu değer BlogKimliği temelinde hesaplanabilir ve bu nedenle veritabanında depolanması gerekmez. Örnek:

using (var context = new BloggingContext())
{
    var blog = context.Blogs.Find(1);
    // Read the current value of an unmapped property
    var rssLink = context.Entry(blog).Property(p => p.RssLink).CurrentValue;

    // Use a string to specify the property name
    var rssLinkAgain = context.Entry(blog).Property("RssLink").CurrentValue;
}

Özelliği bir ayarlayıcıyı kullanıma sunarsa geçerli değer de ayarlanabilir.

Eşlenmemiş özelliklerin değerlerini okumak, eşlenmemiş özelliklerin Entity Framework doğrulamasını gerçekleştirirken yararlıdır. Aynı nedenle geçerli değerler, şu anda bağlam tarafından izlenmeyen varlıkların özellikleri için okunabilir ve ayarlanabilir. Örnek:

using (var context = new BloggingContext())
{
    // Create an entity that is not being tracked
    var blog = new Blog { Name = "ADO.NET Blog" };

    // Read and set the current value of Name as before
    var currentName1 = context.Entry(blog).Property(u => u.Name).CurrentValue;
    context.Entry(blog).Property(u => u.Name).CurrentValue = "My Fancy Blog";
    var currentName2 = context.Entry(blog).Property("Name").CurrentValue;
    context.Entry(blog).Property("Name").CurrentValue = "My Boring Blog";
}

Özgün değerlerin eşlenmemiş özellikler veya bağlam tarafından izlenmeyen varlıkların özellikleri için kullanılamadığını unutmayın.

Bir özelliğin değiştirilmiş olarak işaretlenip işaretlenmediğini denetleme

Aşağıdaki örnekte, tek bir özelliğin değiştirilmiş olarak işaretlenip işaretlenmediğinin nasıl denetlendiği gösterilmektedir:

using (var context = new BloggingContext())
{
    var blog = context.Blogs.Find(1);

    var nameIsModified1 = context.Entry(blog).Property(u => u.Name).IsModified;

    // Use a string for the property name
    var nameIsModified2 = context.Entry(blog).Property("Name").IsModified;
}

SaveChanges çağrıldığında, değiştirilen özelliklerin değerleri veritabanına güncelleştirme olarak gönderilir.

Bir özelliği değiştirilmiş olarak işaretleme

Aşağıdaki örnekte, tek bir özelliğin değiştirilmiş olarak işaretlenmesinin nasıl zorlanacağı gösterilmektedir:

using (var context = new BloggingContext())
{
    var blog = context.Blogs.Find(1);

    context.Entry(blog).Property(u => u.Name).IsModified = true;

    // Use a string for the property name
    context.Entry(blog).Property("Name").IsModified = true;
}

Bir özelliğin değiştirilmiş olarak işaretlenmesi, özelliğin geçerli değeri özgün değeriyle aynı olsa bile SaveChanges çağrıldığında, özelliğin veritabanına bir güncelleştirme gönderilmesini zorlar.

Şu anda tek bir özelliği değiştirildi olarak işaretlendikten sonra değiştirilmeyecek şekilde sıfırlamak mümkün değildir. Bu, gelecek bir sürümde desteklemeyi planladığımız bir şeydir.

Bir varlığın tüm özellikleri için geçerli, özgün ve veritabanı değerlerini okuma

Aşağıdaki örnekte, bir varlığın tüm eşlenmiş özellikleri için geçerli değerlerin, özgün değerlerin ve veritabanındaki değerlerin nasıl okunduğu gösterilmektedir.

using (var context = new BloggingContext())
{
    var blog = context.Blogs.Find(1);

    // Make a modification to Name in the tracked entity
    blog.Name = "My Cool Blog";

    // Make a modification to Name in the database
    context.Database.SqlCommand("update dbo.Blogs set Name = 'My Boring Blog' where Id = 1");

    // Print out current, original, and database values
    Console.WriteLine("Current values:");
    PrintValues(context.Entry(blog).CurrentValues);

    Console.WriteLine("\nOriginal values:");
    PrintValues(context.Entry(blog).OriginalValues);

    Console.WriteLine("\nDatabase values:");
    PrintValues(context.Entry(blog).GetDatabaseValues());
}

public static void PrintValues(DbPropertyValues values)
{
    foreach (var propertyName in values.PropertyNames)
    {
        Console.WriteLine("Property {0} has value {1}",
                          propertyName, values[propertyName]);
    }
}

Geçerli değerler, varlığın özelliklerinin şu anda içerdiği değerlerdir. Özgün değerler, varlık sorgulandığında veritabanından okunan değerlerdir. Veritabanı değerleri, şu anda veritabanında depolandığı için değerlerdir. Veritabanı değerlerini almak, varlık sorgulandığından bu yana veritabanındaki değerler değişmiş olabileceğinde (veritabanında eş zamanlı bir düzenlemenin başka bir kullanıcı tarafından yapılması gibi) yararlıdır.

Başka bir nesneden geçerli veya özgün değerleri ayarlama

İzlenen varlığın geçerli veya özgün değerleri, başka bir nesneden değerler kopyalanarak güncelleştirilebilir. Örnek:

using (var context = new BloggingContext())
{
    var blog = context.Blogs.Find(1);
    var coolBlog = new Blog { Id = 1, Name = "My Cool Blog" };
    var boringBlog = new BlogDto { Id = 1, Name = "My Boring Blog" };

    // Change the current and original values by copying the values from other objects
    var entry = context.Entry(blog);
    entry.CurrentValues.SetValues(coolBlog);
    entry.OriginalValues.SetValues(boringBlog);

    // Print out current and original values
    Console.WriteLine("Current values:");
    PrintValues(entry.CurrentValues);

    Console.WriteLine("\nOriginal values:");
    PrintValues(entry.OriginalValues);
}

public class BlogDto
{
    public int Id { get; set; }
    public string Name { get; set; }
}

Yukarıdaki kodu çalıştırmak şu şekilde yazdırılır:

Current values:
Property Id has value 1
Property Name has value My Cool Blog

Original values:
Property Id has value 1
Property Name has value My Boring Blog

Bu teknik bazen bir varlığı bir hizmet çağrısından veya n katmanlı bir uygulamadaki bir istemciden alınan değerlerle güncelleştirirken kullanılır. Kullanılan nesnenin, adları varlığın özellikleriyle eşleşen özelliklere sahip olduğu sürece varlıkla aynı türde olması gerekmediğini unutmayın. Yukarıdaki örnekte, özgün değerleri güncelleştirmek için BlogDTO örneği kullanılmıştır.

Yalnızca diğer nesneden kopyalandığında farklı değerlere ayarlanmış özelliklerin değiştirilmiş olarak işaretleneceğini unutmayın.

Sözlükten geçerli veya özgün değerleri ayarlama

İzlenen varlığın geçerli veya özgün değerleri, bir sözlükten veya başka bir veri yapısından değerler kopyalanarak güncelleştirilebilir. Örnek:

using (var context = new BloggingContext())
{
    var blog = context.Blogs.Find(1);

    var newValues = new Dictionary<string, object>
    {
        { "Name", "The New ADO.NET Blog" },
        { "Url", "blogs.msdn.com/adonet" },
    };

    var currentValues = context.Entry(blog).CurrentValues;

    foreach (var propertyName in newValues.Keys)
    {
        currentValues[propertyName] = newValues[propertyName];
    }

    PrintValues(currentValues);
}

Özgün değerleri ayarlamak için CurrentValues özelliği yerine OriginalValues özelliğini kullanın.

Özelliği kullanarak bir sözlükten geçerli veya özgün değerleri ayarlama

Yukarıda gösterildiği gibi CurrentValues veya OriginalValues kullanmanın bir alternatifi, her özelliğin değerini ayarlamak için Property yöntemini kullanmaktır. Karmaşık özelliklerin değerlerini ayarlamanız gerektiğinde bu tercih edilebilir. Örnek:

using (var context = new BloggingContext())
{
    var user = context.Users.Find("johndoe1987");

    var newValues = new Dictionary<string, object>
    {
        { "Name", "John Doe" },
        { "Location.City", "Redmond" },
        { "Location.State.Name", "Washington" },
        { "Location.State.Code", "WA" },
    };

    var entry = context.Entry(user);

    foreach (var propertyName in newValues.Keys)
    {
        entry.Property(propertyName).CurrentValue = newValues[propertyName];
    }
}

Yukarıdaki örnekte, karmaşık özelliklere noktalı adlar kullanılarak erişilir. Karmaşık özelliklere erişmenin diğer yolları için bu konunun devamında özellikle karmaşık özelliklerle ilgili iki bölüme bakın.

Geçerli, özgün veya veritabanı değerlerini içeren kopyalanmış nesne oluşturma

Varlığın bir kopyasını oluşturmak için CurrentValues, OriginalValues veya GetDatabaseValues'tan döndürülen DbPropertyValues nesnesi kullanılabilir. Bu kopya, oluşturmak için kullanılan DbPropertyValues nesnesinden özellik değerlerini içerir. Örnek:

using (var context = new BloggingContext())
{
    var blog = context.Blogs.Find(1);

    var clonedBlog = context.Entry(blog).GetDatabaseValues().ToObject();
}

Döndürülen nesnenin varlık olmadığını ve bağlam tarafından izlenmediğini unutmayın. Döndürülen nesnenin diğer nesnelerle ayarlanmış hiçbir ilişkisi de yoktur.

Kopyalanan nesne, özellikle belirli bir türdeki nesnelere veri bağlamayı içeren bir kullanıcı arabiriminin kullanıldığı veritabanındaki eşzamanlı güncelleştirmelerle ilgili sorunları çözmek için yararlı olabilir.

Karmaşık özelliklerin geçerli veya özgün değerlerini alma ve ayarlama

Bir karmaşık nesnenin tamamının değeri, aynı ilkel özellik için olduğu gibi Property yöntemi kullanılarak okunabilir ve ayarlanabilir. Buna ek olarak, karmaşık nesnenin detayına gidebilir ve bu nesnenin özelliklerini, hatta iç içe bir nesneyi okuyabilir veya ayarlayabilirsiniz. Burada bazı örnekler verilmiştir:

using (var context = new BloggingContext())
{
    var user = context.Users.Find("johndoe1987");

    // Get the Location complex object
    var location = context.Entry(user)
                       .Property(u => u.Location)
                       .CurrentValue;

    // Get the nested State complex object using chained calls
    var state1 = context.Entry(user)
                     .ComplexProperty(u => u.Location)
                     .Property(l => l.State)
                     .CurrentValue;

    // Get the nested State complex object using a single lambda expression
    var state2 = context.Entry(user)
                     .Property(u => u.Location.State)
                     .CurrentValue;

    // Get the nested State complex object using a dotted string
    var state3 = context.Entry(user)
                     .Property("Location.State")
                     .CurrentValue;

    // Get the value of the Name property on the nested State complex object using chained calls
    var name1 = context.Entry(user)
                       .ComplexProperty(u => u.Location)
                       .ComplexProperty(l => l.State)
                       .Property(s => s.Name)
                       .CurrentValue;

    // Get the value of the Name property on the nested State complex object using a single lambda expression
    var name2 = context.Entry(user)
                       .Property(u => u.Location.State.Name)
                       .CurrentValue;

    // Get the value of the Name property on the nested State complex object using a dotted string
    var name3 = context.Entry(user)
                       .Property("Location.State.Name")
                       .CurrentValue;
}

Özgün bir değer almak veya ayarlamak için CurrentValue özelliği yerine OriginalValue özelliğini kullanın.

Karmaşık bir özelliğe erişmek için Property veya ComplexProperty yönteminin kullanılabileceğini unutmayın. Ancak, ek Property veya ComplexProperty çağrılarıyla karmaşık nesnede detaya gitmek istiyorsanız ComplexProperty yöntemi kullanılmalıdır.

Karmaşık özelliklere erişmek için DbPropertyValues kullanma

Bir varlığın tüm geçerli, özgün veya veritabanı değerlerini almak için CurrentValues, OriginalValues veya GetDatabaseValues kullandığınızda, karmaşık özelliklerin değerleri iç içe DbPropertyValues nesneleri olarak döndürülür. Bu iç içe nesneler daha sonra karmaşık nesnenin değerlerini almak için kullanılabilir. Örneğin, aşağıdaki yöntem herhangi bir karmaşık özelliğin ve iç içe yerleştirilmiş karmaşık özelliklerin değerleri de dahil olmak üzere tüm özelliklerin değerlerini yazdırır.

public static void WritePropertyValues(string parentPropertyName, DbPropertyValues propertyValues)
{
    foreach (var propertyName in propertyValues.PropertyNames)
    {
        var nestedValues = propertyValues[propertyName] as DbPropertyValues;
        if (nestedValues != null)
        {
            WritePropertyValues(parentPropertyName + propertyName + ".", nestedValues);
        }
        else
        {
            Console.WriteLine("Property {0}{1} has value {2}",
                              parentPropertyName, propertyName,
                              propertyValues[propertyName]);
        }
    }
}

Tüm geçerli özellik değerlerini yazdırmak için yöntemi şu şekilde çağrılır:

using (var context = new BloggingContext())
{
    var user = context.Users.Find("johndoe1987");

    WritePropertyValues("", context.Entry(user).CurrentValues);
}