Aracılığıyla paylaş


N Katmanı Uygulamalarında Veri Alma ve CUD İşlemleri (LINQ to SQL)

Müşteriler veya Siparişler gibi varlık nesnelerini ağ üzerinden bir istemciye seri hale getirdiğinizde, bu varlıklar veri bağlamından ayrılır. Veri bağlamı artık değişikliklerini veya diğer nesnelerle ilişkilerini izlemez. İstemciler yalnızca verileri okuduğu sürece bu bir sorun değildir. İstemcilerin veritabanına yeni satırlar eklemesini sağlamak da oldukça basittir. Ancak, uygulamanız istemcilerin verileri güncelleştirebilmesini veya silebilmesini gerektiriyorsa, çağırmadan DataContext.SubmitChangesönce varlıkları yeni bir veri bağlamı için eklemeniz gerekir. Ayrıca, özgün değerlerle iyimser bir eşzamanlılık denetimi kullanıyorsanız, veritabanına hem özgün varlığı hem de varlığı değiştirildiği gibi sağlamanın bir yolunu da kullanmanız gerekir. Attach Yöntemler, varlıkları ayrıldıktan sonra yeni bir veri bağlamı içine yerleştirmenizi sağlamak için sağlanır.

LINQ to SQL varlıkları yerine ara sunucu nesnelerini seri hale getirseniz bile, verileri veritabanına göndermek için veri erişim katmanında (DAL) bir varlık oluşturmanız ve yeni System.Data.Linq.DataContextbir öğesine eklemeniz gerekir.

LINQ to SQL, varlıkların nasıl seri hale getirildiği konusunda tamamen kayıtsızdır. Windows Communication Foundation (WCF) kullanarak serileştirilebilir sınıflar oluşturmak için Nesne İlişkisel Tasarımcısı ve SQLMetal araçlarını kullanma hakkında daha fazla bilgi için bkz. Nasıl yapılır: Varlıkları Seri Hale Getirilebilir Hale Getirme.

Not

Yalnızca yeni veya seri durumdan çıkarılmış varlıklardaki yöntemleri çağırın Attach . Bir varlığın özgün veri bağlamından ayrılmasının tek yolu seri hale getirmektir. Yeni bir veri bağlamı için kaydedilmemiş bir varlık eklemeye çalışırsanız ve bu varlık hala önceki veri bağlamından yükleyicileri ertelemişse, LINQ to SQL bir özel durum oluşturur. İki farklı veri bağlamından ertelenen yükleyicileri olan bir varlık, bu varlık üzerinde ekleme, güncelleştirme ve silme işlemleri gerçekleştirdiğinizde istenmeyen sonuçlara neden olabilir. Ertelenmiş yükleyiciler hakkında daha fazla bilgi için bkz . Ertelenmiş ve Anında Yükleme.

Veri Alınıyor

İstemci Yöntemi Çağrısı

Aşağıdaki örneklerde, Bir Windows Forms istemcisinden DAL'ye yapılan örnek yöntem çağrısı gösterilmektedir. Bu örnekte DAL, Bir Windows Hizmet Kitaplığı olarak uygulanır:

Private Function GetProdsByCat_Click(ByVal sender As Object, ByVal e _  
    As EventArgs)  
  
    ' Create the WCF client proxy.  
    Dim proxy As New NorthwindServiceReference.Service1Client  
  
    ' Call the method on the service.  
    Dim products As NorthwindServiceReference.Product() = _  
        proxy.GetProductsByCategory(1)  
  
    ' If the database uses original values for concurrency checks,  
    ' the client needs to store them and pass them back to the  
    ' middle tier along with the new values when updating data.  
  
    For Each v As NorthwindClient1.NorthwindServiceReference.Product _  
        In products  
        ' Persist to a List(Of Product) declared at class scope.  
        ' Additional change-tracking logic is the responsibility  
        ' of the presentation tier and/or middle tier.  
        originalProducts.Add(v)  
    Next  
  
    ' (Not shown) Bind the products list to a control  
    ' and/or perform whatever processing is necessary.  
End Function  
private void GetProdsByCat_Click(object sender, EventArgs e)  
{  
    // Create the WCF client proxy.  
    NorthwindServiceReference.Service1Client proxy =
    new NorthwindClient.NorthwindServiceReference.Service1Client();  
  
    // Call the method on the service.  
    NorthwindServiceReference.Product[] products =
    proxy.GetProductsByCategory(1);  
  
    // If the database uses original values for concurrency checks,
    // the client needs to store them and pass them back to the
    // middle tier along with the new values when updating data.  
    foreach (var v in products)  
    {  
        // Persist to a list<Product> declared at class scope.  
        // Additional change-tracking logic is the responsibility  
        // of the presentation tier and/or middle tier.  
        originalProducts.Add(v);  
    }  
  
    // (Not shown) Bind the products list to a control  
    // and/or perform whatever processing is necessary.  
    }  

Orta Katman Uygulaması

Aşağıdaki örnekte orta katmandaki arabirim yönteminin bir uygulaması gösterilmektedir. Dikkate almak istediğiniz iki ana nokta şunlardır:

  • DataContext yöntemi kapsamında bildirilir.

  • yöntemi, gerçek sonuçların bir IEnumerable koleksiyonunu döndürür. Seri hale getirici, sonuçları istemci/sunu katmanına geri göndermek için sorguyu yürütür. Orta katmanda sorgu sonuçlarına yerel olarak erişmek için, veya sorgu değişkenini çağırarak ToListToArray yürütmeyi zorlayabilirsiniz. Daha sonra bu listeyi veya diziyi olarak IEnumerabledöndürebilirsiniz.

Public Function GetProductsByCategory(ByVal categoryID As Integer) _  
    As IEnumerable(Of Product)  
  
    Dim db As New NorthwindClasses1DataContext(connectionString)  
    Dim productQuery = _  
    From prod In db.Products _  
    Where prod.CategoryID = categoryID _  
    Select prod  
  
    Return productQuery.AsEnumerable()  
  
End Function  
public IEnumerable<Product> GetProductsByCategory(int categoryID)  
{  
    NorthwindClasses1DataContext db =
    new NorthwindClasses1DataContext(connectionString);  
  
    IEnumerable<Product> productQuery =  
    from prod in db.Products  
    where prod.CategoryID == categoryID  
    select prod;  
  
    return productQuery.AsEnumerable();
}  

Veri bağlamı örneğinin ömrü bir "çalışma birimi" olmalıdır. Gevşek bir şekilde bağlanmış bir ortamda, bir iş birimi genellikle küçüktür, belki de tek bir iyimser işlem, tek bir çağrısı da dahil olmak SubmitChangesüzere. Bu nedenle, veri bağlamı oluşturulur ve yöntem kapsamında atılır. İş birimi iş kuralları mantığına çağrılar içeriyorsa, genel olarak bu işlemin tamamının örneğini DataContext tutmak istersiniz. Her durumda, DataContext örneklerin rastgele sayıda işlemde uzun süre canlı tutulması amaçlanmamıştır.

Bu yöntem Product nesnelerini döndürür, ancak her bir Product ile ilişkilendirilmiş Order_Detail nesne koleksiyonunu döndürmez. DataLoadOptions Bu varsayılan davranışı değiştirmek için nesnesini kullanın. Daha fazla bilgi için bkz . Nasıl yapılır: İlgili Verilerin Ne Kadar Alındiğini Denetleme.

Veri ekleme

Yeni bir nesne eklemek için, sunu katmanı yalnızca orta katman arabiriminde ilgili yöntemi çağırır ve eklenecek yeni nesneyi geçirir. Bazı durumlarda, istemcinin yalnızca bazı değerleri geçirmesi ve orta katmanın tam nesneyi oluşturması daha verimli olabilir.

Orta Katman Uygulaması

Orta katmanda yeni DataContext bir oluşturulur, nesnesi yöntemi kullanılarak InsertOnSubmit öğesine eklenir DataContext ve çağrıldığında SubmitChanges nesnesi eklenir. Özel durumlar, geri çağırmalar ve hata koşulları diğer Web hizmeti senaryolarında olduğu gibi işlenebilir.

' No call to Attach is necessary for inserts.  
Public Sub InsertOrder(ByVal o As Order)  
  
    Dim db As New NorthwindClasses1DataContext(connectionString)  
    db.Orders.InsertOnSubmit(o)  
  
    ' Exception handling not shown.  
    db.SubmitChanges()  
  
End Sub  
// No call to Attach is necessary for inserts.  
    public void InsertOrder(Order o)  
    {  
        NorthwindClasses1DataContext db = new NorthwindClasses1DataContext(connectionString);  
        db.Orders.InsertOnSubmit(o);  
  
        // Exception handling not shown.  
        db.SubmitChanges();  
    }  

Veri silme

Mevcut bir nesneyi veritabanından silmek için, sunu katmanı orta katman arabiriminde ilgili yöntemi çağırır ve silinecek nesnenin özgün değerlerini içeren kopyasını geçirir.

Silme işlemleri iyimser eşzamanlılık denetimleri içerir ve silinecek nesnenin önce yeni veri bağlamlarına eklenmesi gerekir. Bu örnekte parametresi, nesnenin Boolean bir zaman damgası (RowVersion) olmadığını belirtmek için ayarlanmıştır false . Veritabanı tablonuz her kayıt için zaman damgaları oluşturuyorsa, özellikle istemci için eşzamanlılık denetimleri çok daha basittir. Yalnızca özgün veya değiştirilmiş nesneyi geçirin ve parametresini Boolean olarak trueayarlayın. Her durumda, orta katmanda genellikle öğesini yakalamak ChangeConflictExceptiongerekir. İyimser eşzamanlılık çakışmalarını işleme hakkında daha fazla bilgi için bkz . İyimser Eşzamanlılık: Genel Bakış.

İlişkili tablolarda yabancı anahtar kısıtlamaları olan varlıkları silerken, önce koleksiyonlarındaki EntitySet<TEntity> tüm nesneleri silmeniz gerekir.

' Attach is necessary for deletes.  
Public Sub DeleteOrder(ByVal order As Order)  
    Dim db As New NorthwindClasses1DataContext(connectionString)  
  
    db.Orders.Attach(order, False)  
    ' This will throw an exception if the order has order details.  
    db.Orders.DeleteOnSubmit(order)  
  
    Try  
        ' ConflictMode is an optional parameter.  
        db.SubmitChanges(ConflictMode.ContinueOnConflict)  
  
    Catch ex As ChangeConflictException  
        ' Get conflict information, and take actions  
        ' that are appropriate for your application.  
        ' See MSDN Article "How to: Manage Change  
        ' Conflicts (LINQ to SQL).  
  
    End Try  
End Sub  
// Attach is necessary for deletes.  
public void DeleteOrder(Order order)  
{  
    NorthwindClasses1DataContext db = new NorthwindClasses1DataContext(connectionString);  
  
    db.Orders.Attach(order, false);  
    // This will throw an exception if the order has order details.  
    db.Orders.DeleteOnSubmit(order);  
    try  
    {  
        // ConflictMode is an optional parameter.  
        db.SubmitChanges(ConflictMode.ContinueOnConflict);  
    }  
    catch (ChangeConflictException e)  
    {  
       // Get conflict information, and take actions  
       // that are appropriate for your application.  
       // See MSDN Article How to: Manage Change Conflicts (LINQ to SQL).  
    }  
}  

Verileri Güncelleştirme

LINQ to SQL, iyimser eşzamanlılık içeren bu senaryolarda güncelleştirmeleri destekler:

  • Zaman damgalarına veya RowVersion sayılarına göre iyimser eşzamanlılık.

  • Varlık özelliklerinin bir alt kümesinin özgün değerlerine dayalı iyimser eşzamanlılık.

  • Özgün ve değiştirilmiş varlıkların tamamını temel alan iyimser eşzamanlılık.

Ayrıca, müşteri ve ilişkili Order nesnelerinin koleksiyonu gibi ilişkileriyle birlikte bir varlıkta güncelleştirmeler veya silme işlemleri gerçekleştirebilirsiniz. İstemcide varlık nesnelerinin ve alt (EntitySet) koleksiyonlarının grafiğinde değişiklik yaptığınızda ve iyimser eşzamanlılık denetimleri özgün değerler gerektirdiğinde, istemcinin her varlık ve EntitySet<TEntity> nesne için bu özgün değerleri sağlaması gerekir. İstemcilerin tek bir yöntem çağrısında ilgili güncelleştirmeler, silmeler ve eklemeler yapmalarını sağlamak istiyorsanız, istemciye her varlıkta gerçekleştirilecek işlem türünü belirtmek için bir yol sağlamanız gerekir. Orta katmanda, çağrısı yapmadan önce her varlık için uygun Attach yöntemi ve ardından InsertOnSubmit, DeleteAllOnSubmitveya InsertOnSubmit (eklemeler için olmadan Attach) çağırmanız SubmitChangesgerekir. Güncelleştirmeleri denemeden önce özgün değerleri almak için veritabanından veri almayın.

İyimser eşzamanlılık hakkında daha fazla bilgi için bkz . İyimser Eşzamanlılık: Genel Bakış. İyimser eşzamanlılık değişikliği çakışmalarını çözme hakkında ayrıntılı bilgi için bkz . Nasıl yapılır: Değişiklik Çakışmalarını Yönetme.

Aşağıdaki örneklerde her senaryo gösterilmektedir:

Zaman damgalarıyla iyimser eşzamanlılık

' Assume that "customer" has been sent by client.  
' Attach with "true" to say this is a modified entity  
' and it can be checked for optimistic concurrency  
' because it has a column that is marked with the  
' "RowVersion" attribute.  
  
db.Customers.Attach(customer, True)  
  
Try  
    ' Optional: Specify a ConflictMode value  
    ' in call to SubmitChanges.  
    db.SubmitChanges()  
Catch ex As ChangeConflictException  
    ' Handle conflict based on options provided.  
    ' See MSDN article "How to: Manage Change  
    ' Conflicts (LINQ to SQL)".  
End Try  
// Assume that "customer" has been sent by client.  
// Attach with "true" to say this is a modified entity  
// and it can be checked for optimistic concurrency because  
//  it has a column that is marked with "RowVersion" attribute  
db.Customers.Attach(customer, true)  
try  
{  
    // Optional: Specify a ConflictMode value  
    // in call to SubmitChanges.  
    db.SubmitChanges();  
}  
catch(ChangeConflictException e)  
{  
    // Handle conflict based on options provided  
    // See MSDN article How to: Manage Change Conflicts (LINQ to SQL).  
}  

Özgün Değerlerin Alt Kümesi ile

Bu yaklaşımda istemci, değiştirilecek değerlerle birlikte tam serileştirilmiş nesneyi döndürür.

Public Sub UpdateProductInventory(ByVal p As Product, ByVal _  
    unitsInStock As Short?, ByVal unitsOnOrder As Short?)  
  
    Using db As New NorthwindClasses1DataContext(connectionString)  
        ' p is the original unmodified product  
        ' that was obtained from the database.  
        ' The client kept a copy and returns it now.  
        db.Products.Attach(p, False)  
  
        ' Now that the original values are in the data context,  
        ' apply the changes.  
        p.UnitsInStock = unitsInStock  
        p.UnitsOnOrder = unitsOnOrder  
  
        Try  
            ' Optional: Specify a ConflictMode value  
            ' in call to SubmitChanges.  
            db.SubmitChanges()  
  
        Catch ex As Exception  
            ' Handle conflict based on options provided.  
            ' See MSDN article "How to: Manage Change Conflicts  
            ' (LINQ to SQL)".  
        End Try  
    End Using  
End Sub  
public void UpdateProductInventory(Product p, short? unitsInStock, short? unitsOnOrder)  
{  
    using (NorthwindClasses1DataContext db = new NorthwindClasses1DataContext(connectionString))  
    {  
        // p is the original unmodified product  
        // that was obtained from the database.  
        // The client kept a copy and returns it now.  
        db.Products.Attach(p, false);  
  
        // Now that the original values are in the data context, apply the changes.  
        p.UnitsInStock = unitsInStock;  
        p.UnitsOnOrder = unitsOnOrder;  
        try  
        {  
             // Optional: Specify a ConflictMode value  
             // in call to SubmitChanges.  
             db.SubmitChanges();  
        }  
        catch (ChangeConflictException e)  
        {  
            // Handle conflict based on provided options.  
            // See MSDN article How to: Manage Change Conflicts  
            // (LINQ to SQL).  
        }  
    }  
}  

Eksiksiz Varlıklar ile

Public Sub UpdateProductInfo(ByVal newProd As Product, ByVal _  
    originalProd As Product)  
  
    Using db As New NorthwindClasses1DataContext(connectionString)  
        db.Products.Attach(newProd, originalProd)  
  
        Try  
            ' Optional: Specify a ConflictMode value  
            ' in call to SubmitChanges.  
            db.SubmitChanges()  
  
        Catch ex As Exception  
            ' Handle potential change conflict in whatever way  
            ' is appropriate for your application.  
            ' For more information, see the MSDN article  
            ' "How to: Manage Change Conflicts (LINQ to  
            ' SQL)".  
        End Try  
  
    End Using  
End Sub  
public void UpdateProductInfo(Product newProd, Product originalProd)  
{  
     using (NorthwindClasses1DataContext db = new  
        NorthwindClasses1DataContext(connectionString))  
     {  
         db.Products.Attach(newProd, originalProd);  
         try  
         {  
               // Optional: Specify a ConflictMode value  
               // in call to SubmitChanges.  
               db.SubmitChanges();  
         }  
        catch (ChangeConflictException e)  
        {  
            // Handle potential change conflict in whatever way  
            // is appropriate for your application.  
            // For more information, see the MSDN article  
            // How to: Manage Change Conflicts (LINQ to SQL)/  
        }
    }  
}  

Bir koleksiyonu güncelleştirmek için yerine öğesini çağırın AttachAllAttach.

Beklenen Varlık Üyeleri

Daha önce belirtildiği gibi, yöntemleri çağırmadan Attach önce varlık nesnesinin yalnızca belirli üyelerinin ayarlanması gerekir. Ayarlanması gereken varlık üyeleri aşağıdaki ölçütleri karşılamalıdır:

  • Varlığın kimliğinin bir parçası olun.

  • Değiştirilmesi beklenir.

  • Bir zaman damgası olun veya UpdateCheck özniteliğinin dışında Neverbir değere ayarlanmış olması gerekir.

Bir tabloda iyimser eşzamanlılık denetimi için zaman damgası veya sürüm numarası kullanılıyorsa, çağırmadan Attachönce bu üyeleri ayarlamanız gerekir. Üye, özelliğin bu Column özniteliğinde true olarak ayarlandığında iyimser eşzamanlılık denetimi IsVersion için ayrılmıştır. İstenen güncelleştirmeler yalnızca sürüm numarası veya zaman damgası değerleri veritabanında aynıysa gönderilir.

Üye olarak ayarlanmadığı UpdateCheckNeversürece iyimser eşzamanlılık denetiminde de bir üye kullanılır. Varsayılan değer, başka bir değer belirtilmemişse olur Always .

Bu gerekli üyelerden herhangi biri eksikse, sırasında SubmitChanges bir ChangeConflictException oluşturulur ("Satır bulunamadı veya değiştirilmedi").

Durum

Bir varlık nesnesi örneğe eklendikten DataContext sonra nesnenin durumunda PossiblyModified olduğu kabul edilir. Ekli bir nesneyi göz önünde bulundurulmaya Modifiedzorlamanın üç yolu vardır.

  1. Değiştirilmemiş olarak ekleyin ve alanları doğrudan değiştirin.

  2. Attach Geçerli ve özgün nesne örneklerini alan aşırı yükle ekleyin. Bu, hangi alanların değiştiğini otomatik olarak bilmesi için değişiklik izleyicisine eski ve yeni değerler sağlar.

  3. İkinci bir Boole Attach parametresini (true olarak ayarlanmış) alan aşırı yükle ekleyin. Bu, değişiklik izleyicisine özgün değer sağlamak zorunda kalmadan değiştirilen nesneyi dikkate almalarını söyler. Bu yaklaşımda, nesnenin bir sürüm/zaman damgası alanı olmalıdır.

Daha fazla bilgi için bkz . Nesne Durumları ve Değişiklik İzleme.

Kimlik Önbelleği'nde zaten eklenen nesneyle aynı kimliğe sahip bir varlık nesnesi oluşuyorsa, bir DuplicateKeyException oluşturulur.

Bir IEnumerable nesne kümesiyle eklediğinizde, DuplicateKeyException zaten var olan bir anahtar mevcut olduğunda bir oluşturulur. Kalan nesneler eklenmez.

Ayrıca bkz.