Kendi Kendine İzleme Varlıkları İzlenecek Yol
Önemli
Kendini izleyen varlıklar şablonunu kullanmanızı artık önermiyoruz. Yalnızca mevcut uygulamaları desteklemek için sunulmaya devam edecektir. Uygulamanız bağlantısız varlık graflarıyla çalışmayı gerektiriyorsa, topluluk tarafından daha etkin bir şekilde geliştirilen Kendini İzleyen Varlıklara benzer bir teknoloji olan İzlenebilir Varlıklar veya düşük düzeyli değişiklik izleme API’lerini kullanarak özel kod yazma gibi diğer alternatifleri göz önünde bulundurun.
Bu kılavuzda, bir Windows Communication Foundation (WCF) hizmetinin varlık grafı döndüren bir işlemi kullanıma sunma senaryosu gösterilmektedir. Ardından, bir istemci uygulaması bu grafiği işleyip değişiklikleri Entity Framework kullanarak güncelleştirmeleri doğrulayan ve veritabanına kaydeden bir hizmet işlemine gönderir.
Bu kılavuzu tamamlamadan önce Kendi Kendine İzleme Varlıkları sayfasını okuduğunuzdan emin olun.
Bu izlenecek yol aşağıdaki eylemleri tamamlar:
- Erişecek bir veritabanı oluşturur.
- Modeli içeren bir sınıf kitaplığı oluşturur.
- Kendi Kendine İzleme Varlık Oluşturucu şablonuna geçiş yapılır.
- Varlık sınıflarını ayrı bir projeye taşır.
- Varlıkları sorgulamak ve kaydetmek için işlemleri kullanıma sunan bir WCF hizmeti oluşturur.
- Hizmeti kullanan istemci uygulamaları (Konsol ve WPF) oluşturur.
Bu kılavuzda Önce Veritabanı kullanacağız ancak aynı teknikler Model First için de aynı şekilde geçerlidir.
Önkoşullar
Bu kılavuzu tamamlamak için Visual Studio'nun son sürümünü kullanmanız gerekir.
Veritabanı Oluşturma
Visual Studio ile yüklenen veritabanı sunucusu, yüklediğiniz Visual Studio sürümüne bağlı olarak farklıdır:
- Visual Studio 2012 kullanıyorsanız bir LocalDB veritabanı oluşturacaksınız.
- Visual Studio 2010 kullanıyorsanız bir SQL Express veritabanı oluşturacaksınız.
Şimdi veritabanını oluşturalım.
- Visual Studio’yu açın
- Görünüm -> Sunucu Gezgini
- Veri Bağlan ions -> Bağlan Ekle... öğesine sağ tıklayın
- Veri kaynağı olarak Microsoft SQL Server'ı seçmeniz gerekmeden önce Sunucu Gezgini'nden bir veritabanına bağlanmadıysanız
- Hangisini yüklediğinize bağlı olarak LocalDB veya SQL Express'e Bağlan
- Veritabanı adı olarak STESample girin
- Tamam'ı seçtiğinizde yeni veritabanı oluşturmak isteyip istemediğiniz sorulur ve Evet'i seçin
- Yeni veritabanı artık Sunucu Gezgini'nde görünür
- Visual Studio 2012 kullanıyorsanız
- Sunucu Gezgini'nde veritabanına sağ tıklayın ve Yeni Sorgu'yu seçin
- Aşağıdaki SQL'i yeni sorguya kopyalayın, ardından sorguya sağ tıklayın ve Yürüt'e tıklayın
- Visual Studio 2010 kullanıyorsanız
- Veri -> İşlem SQL Düzenleyicisi -> Yeni Sorgu Bağlan... öğesini seçin.
- Sunucu adı olarak .\SQLEXPRESS yazın ve Tamam'a tıklayın
- Sorgu düzenleyicisinin üst kısmındaki açılan listeden STESample veritabanını seçin
- Aşağıdaki SQL'i yeni sorguya kopyalayın, ardından sorguya sağ tıklayın ve SQL Yürüt'e tıklayın
CREATE TABLE [dbo].[Blogs] (
[BlogId] INT IDENTITY (1, 1) NOT NULL,
[Name] NVARCHAR (200) NULL,
[Url] NVARCHAR (200) NULL,
CONSTRAINT [PK_dbo.Blogs] PRIMARY KEY CLUSTERED ([BlogId] ASC)
);
CREATE TABLE [dbo].[Posts] (
[PostId] INT IDENTITY (1, 1) NOT NULL,
[Title] NVARCHAR (200) NULL,
[Content] NTEXT NULL,
[BlogId] INT NOT NULL,
CONSTRAINT [PK_dbo.Posts] PRIMARY KEY CLUSTERED ([PostId] ASC),
CONSTRAINT [FK_dbo.Posts_dbo.Blogs_BlogId] FOREIGN KEY ([BlogId]) REFERENCES [dbo].[Blogs] ([BlogId]) ON DELETE CASCADE
);
SET IDENTITY_INSERT [dbo].[Blogs] ON
INSERT INTO [dbo].[Blogs] ([BlogId], [Name], [Url]) VALUES (1, N'ADO.NET Blog', N'blogs.msdn.com/adonet')
SET IDENTITY_INSERT [dbo].[Blogs] OFF
INSERT INTO [dbo].[Posts] ([Title], [Content], [BlogId]) VALUES (N'Intro to EF', N'Interesting stuff...', 1)
INSERT INTO [dbo].[Posts] ([Title], [Content], [BlogId]) VALUES (N'What is New', N'More interesting stuff...', 1)
Modeli Oluşturma
İlk olarak, modeli yerleştirmek için bir projeye ihtiyacımız var.
- Dosya -> Yeni -> Proje...
- Sol bölmeden Visual C# öğesini ve ardından Sınıf Kitaplığı'nı seçin
- Ad olarak STESample girin ve Tamam'a tıklayın
Şimdi EF Tasarım Aracı veritabanımıza erişmek için basit bir model oluşturacağız:
- Proje -> Yeni Öğe Ekle...
- Sol bölmeden Veri'yi seçin ve varlık veri modelini ADO.NET
- Ad olarak BloggingModel yazın ve Tamam'a tıklayın
- Veritabanından oluştur'a tıklayın ve İleri'ye tıklayın
- Önceki bölümde oluşturduğunuz veritabanının bağlantı bilgilerini girin
- bağlantı dizesi adı olarak BloggingContext yazın ve İleri'ye tıklayın
- Tablolar'ın yanındaki kutuyu işaretleyin ve Son'a tıklayın
STE Kodu Oluşturma ile Değiştirme
Şimdi varsayılan kod oluşturmayı devre dışı bırakmamız ve Kendi kendine İzleme Varlıklarına değiştirmemiz gerekiyor.
Visual Studio 2012 kullanıyorsanız
- Çözüm Gezgini'de BloggingModel.edmx'i genişletin ve BloggingModel.tt silin ve BloggingModel.Context.ttBu, varsayılan kod oluşturmayı devre dışı bırakır
- EF Tasarım Aracı yüzeyinde boş bir alana sağ tıklayın ve Kod Oluşturma Öğesi Ekle... öğesini seçin.
- Sol bölmeden Çevrimiçi'yi seçin ve STE Oluşturucu için arama yapın
- C# için STE Oluşturucu şablonunu seçin, ad olarak STETemplate yazın ve Ekle'ye tıklayın
- STETemplate.tt ve STETemplate.Context.tt dosyaları BloggingModel.edmx dosyasının altına eklenir
Visual Studio 2010 kullanıyorsanız
- EF Tasarım Aracı yüzeyinde boş bir alana sağ tıklayın ve Kod Oluşturma Öğesi Ekle... öğesini seçin.
- Sol bölmeden Kod'a tıklayın ve ardından Kendi Kendine İzleme Varlık Oluşturucu'ADO.NET
- Ad olarak STETemplate yazın ve Ekle'ye tıklayın
- STETemplate.tt ve STETemplate.Context.tt dosyaları doğrudan projenize eklenir
Varlık Türlerini Ayrı Projeye Taşıma
Kendi Kendine İzleme Varlıklarını kullanmak için istemci uygulamamızın modelimizden oluşturulan varlık sınıflarına erişmesi gerekir. Modelin tamamını istemci uygulamasına göstermek istemediğimiz için varlık sınıflarını ayrı bir projeye taşıyacağız.
İlk adım, var olan projede varlık sınıfları oluşturma işlemini durdurmaktır:
- Çözüm Gezgini STETemplate.tt sağ tıklayın ve Özellikler'i seçin
- Özellikler penceresinde CustomTool özelliğinden TextTemplatingFileGenerator öğesini temizleyin
- Çözüm Gezgini'da STETemplate.tt genişletin ve altında iç içe yerleştirilmiş tüm dosyaları silin
Şimdi yeni bir proje ekleyecek ve içindeki varlık sınıflarını oluşturacağız
Dosya -> Ekle -> Proje...
Sol bölmeden Visual C# öğesini ve ardından Sınıf Kitaplığı'nı seçin
Ad olarak STESample.Entities yazın ve Tamam'a tıklayın
Proje -> Varolan ÖğeYi Ekle...
STESample proje klasörüne gidin
Tüm Dosyaları görüntülemek için seçin (*.*)
STETemplate.tt dosyasını seçin
Ekle düğmesinin yanındaki açılan oka tıklayın ve Bağlantı Olarak Ekle'yi seçin
Ayrıca varlık sınıflarının bağlamla aynı ad alanında oluşturulduğundan da emin olacağız. Bu, uygulamamız genelinde eklememiz gereken using deyimlerinin sayısını azaltır.
- Çözüm Gezgini bağlı STETemplate.tt sağ tıklayın ve Özellikler'i seçin
- Özellikler penceresinde Özel Araç Ad Alanı'nı STESample olarak ayarlayın
STE şablonu tarafından oluşturulan kodun derlenmesi için System.Runtime.Serialization başvurusu gerekir. Bu kitaplık, serileştirilebilir varlık türlerinde kullanılan WCF DataContract ve DataMember öznitelikleri için gereklidir.
- Çözüm Gezgini'da STESample.Entities projesine sağ tıklayın ve Başvuru Ekle... öğesini seçin.
- Visual Studio 2012'de - System.Runtime.Serialization'ın yanındaki kutuyu işaretleyin ve Tamam'a tıklayın
- Visual Studio 2010'da System.Runtime.Serialization'ı seçin ve Tamam'a tıklayın
Son olarak, içinde bağlamımız bulunan projenin varlık türlerine bir başvurusu olması gerekir.
- Çözüm Gezgini'da STESample projesine sağ tıklayın ve Başvuru Ekle... seçeneğini belirleyin.
- Visual Studio 2012'de sol bölmeden Çözüm'e tıklayın, STESample.Entities'ın yanındaki kutuyu işaretleyin ve Tamam'a tıklayın
- Visual Studio 2010'da Projeler sekmesini seçin, STESample.Entities öğesini seçin ve Tamam'a tıklayın
Dekont
Varlık türlerini ayrı bir projeye taşımak için bir diğer seçenek de şablon dosyasını varsayılan konumundan bağlamak yerine taşımaktır. Bunu yaparsanız, edmx dosyasının göreli yolunu sağlamak için şablondaki inputFile değişkenini güncelleştirmeniz gerekir (bu örnekte .. \BloggingModel.edmx).
WCF Hizmeti Oluşturma
Şimdi verilerimizi kullanıma sunma amacıyla bir WCF Hizmeti ekleme zamanı geldi, projeyi oluşturarak başlayacağız.
- Dosya -> Ekle -> Proje...
- Sol bölmeden Visual C# öğesini ve ardından WCF Hizmet Uygulaması'nı seçin
- Ad olarak STESample.Service girin ve Tamam'a tıklayın
- System.Data.Entity derlemesine başvuru ekleme
- STESample ve STESample.Entities projelerine başvuru ekleme
Çalışma zamanında bulunması için EF bağlantı dizesi bu projeye kopyalamamız gerekir.
- **STESample **projesi için App.Config dosyasını açın ve connectionStrings öğesini kopyalayın
- connectionStrings öğesini STESample.Service projesinde Web.Config dosyasının yapılandırma öğesinin alt öğesi olarak yapıştırın
Şimdi gerçek hizmeti uygulama zamanı.
- IService1.cs dosyasını açın ve içeriğini aşağıdaki kodla değiştirin
using System.Collections.Generic;
using System.ServiceModel;
namespace STESample.Service
{
[ServiceContract]
public interface IService1
{
[OperationContract]
List<Blog> GetBlogs();
[OperationContract]
void UpdateBlog(Blog blog);
}
}
- Service1.svc dosyasını açın ve içeriğini aşağıdaki kodla değiştirin
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
namespace STESample.Service
{
public class Service1 : IService1
{
/// <summary>
/// Gets all the Blogs and related Posts.
/// </summary>
public List<Blog> GetBlogs()
{
using (BloggingContext context = new BloggingContext())
{
return context.Blogs.Include("Posts").ToList();
}
}
/// <summary>
/// Updates Blog and its related Posts.
/// </summary>
public void UpdateBlog(Blog blog)
{
using (BloggingContext context = new BloggingContext())
{
try
{
// TODO: Perform validation on the updated order before applying the changes.
// The ApplyChanges method examines the change tracking information
// contained in the graph of self-tracking entities to infer the set of operations
// that need to be performed to reflect the changes in the database.
context.Blogs.ApplyChanges(blog);
context.SaveChanges();
}
catch (UpdateException)
{
// To avoid propagating exception messages that contain sensitive data to the client tier
// calls to ApplyChanges and SaveChanges should be wrapped in exception handling code.
throw new InvalidOperationException("Failed to update. Try your request again.");
}
}
}
}
}
Hizmeti Konsol Uygulamasından Kullanma
Şimdi hizmetimizi kullanan bir konsol uygulaması oluşturalım.
- Dosya -> Yeni -> Proje...
- Sol bölmeden Visual C# öğesini ve ardından Konsol Uygulaması'nı seçin
- Ad olarak STESample.ConsoleTest yazın ve Tamam'a tıklayın
- STESample.Entities projesine başvuru ekleme
WCF hizmetimiz için bir hizmet başvurusuna ihtiyacımız var
- Çözüm Gezgini'da STESample.ConsoleTest projesine sağ tıklayın ve Hizmet Başvurusu Ekle... öğesini seçin.
- Bul'a tıklayın
- Ad alanı olarak BloggingService girin ve Tamam'a tıklayın
Artık hizmeti kullanmak için bazı kodlar yazabiliriz.
- Program.cs dosyasını açın ve içeriğini aşağıdaki kodla değiştirin.
using STESample.ConsoleTest.BloggingService;
using System;
using System.Linq;
namespace STESample.ConsoleTest
{
class Program
{
static void Main(string[] args)
{
// Print out the data before we change anything
Console.WriteLine("Initial Data:");
DisplayBlogsAndPosts();
// Add a new Blog and some Posts
AddBlogAndPost();
Console.WriteLine("After Adding:");
DisplayBlogsAndPosts();
// Modify the Blog and one of its Posts
UpdateBlogAndPost();
Console.WriteLine("After Update:");
DisplayBlogsAndPosts();
// Delete the Blog and its Posts
DeleteBlogAndPost();
Console.WriteLine("After Delete:");
DisplayBlogsAndPosts();
Console.WriteLine("Press any key to exit...");
Console.ReadKey();
}
static void DisplayBlogsAndPosts()
{
using (var service = new Service1Client())
{
// Get all Blogs (and Posts) from the service
// and print them to the console
var blogs = service.GetBlogs();
foreach (var blog in blogs)
{
Console.WriteLine(blog.Name);
foreach (var post in blog.Posts)
{
Console.WriteLine(" - {0}", post.Title);
}
}
}
Console.WriteLine();
Console.WriteLine();
}
static void AddBlogAndPost()
{
using (var service = new Service1Client())
{
// Create a new Blog with a couple of Posts
var newBlog = new Blog
{
Name = "The New Blog",
Posts =
{
new Post { Title = "Welcome to the new blog"},
new Post { Title = "What's new on the new blog"}
}
};
// Save the changes using the service
service.UpdateBlog(newBlog);
}
}
static void UpdateBlogAndPost()
{
using (var service = new Service1Client())
{
// Get all the Blogs
var blogs = service.GetBlogs();
// Use LINQ to Objects to find The New Blog
var blog = blogs.First(b => b.Name == "The New Blog");
// Update the Blogs name
blog.Name = "The Not-So-New Blog";
// Update one of the related posts
blog.Posts.First().Content = "Some interesting content...";
// Save the changes using the service
service.UpdateBlog(blog);
}
}
static void DeleteBlogAndPost()
{
using (var service = new Service1Client())
{
// Get all the Blogs
var blogs = service.GetBlogs();
// Use LINQ to Objects to find The Not-So-New Blog
var blog = blogs.First(b => b.Name == "The Not-So-New Blog");
// Mark all related Posts for deletion
// We need to call ToList because each Post will be removed from the
// Posts collection when we call MarkAsDeleted
foreach (var post in blog.Posts.ToList())
{
post.MarkAsDeleted();
}
// Mark the Blog for deletion
blog.MarkAsDeleted();
// Save the changes using the service
service.UpdateBlog(blog);
}
}
}
}
Artık uygulamayı çalıştırarak çalışır durumda görebilirsiniz.
- Çözüm Gezgini'da STESample.ConsoleTest projesine sağ tıklayın ve Hata Ayıkla -> Yeni örneği başlat'ı seçin
Uygulama yürütürken aşağıdaki çıkışı görürsünüz.
Initial Data:
ADO.NET Blog
- Intro to EF
- What is New
After Adding:
ADO.NET Blog
- Intro to EF
- What is New
The New Blog
- Welcome to the new blog
- What's new on the new blog
After Update:
ADO.NET Blog
- Intro to EF
- What is New
The Not-So-New Blog
- Welcome to the new blog
- What's new on the new blog
After Delete:
ADO.NET Blog
- Intro to EF
- What is New
Press any key to exit...
Wpf Uygulamasından Hizmeti Kullanma
Şimdi hizmetimizi kullanan bir WPF uygulaması oluşturalım.
- Dosya -> Yeni -> Proje...
- Sol bölmeden Visual C# öğesini ve ardından WPF Uygulaması'nı seçin
- Ad olarak STESample.WPFTest girin ve Tamam'a tıklayın
- STESample.Entities projesine başvuru ekleme
WCF hizmetimiz için bir hizmet başvurusuna ihtiyacımız var
- Çözüm Gezgini'da STESample.WPFTest projesine sağ tıklayın ve Hizmet Başvurusu Ekle... öğesini seçin.
- Bul'a tıklayın
- Ad alanı olarak BloggingService girin ve Tamam'a tıklayın
Artık hizmeti kullanmak için bazı kodlar yazabiliriz.
- MainWindow.xaml dosyasını açın ve içeriğini aşağıdaki kodla değiştirin.
<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:STESample="clr-namespace:STESample;assembly=STESample.Entities"
mc:Ignorable="d" x:Class="STESample.WPFTest.MainWindow"
Title="MainWindow" Height="350" Width="525" Loaded="Window_Loaded">
<Window.Resources>
<CollectionViewSource
x:Key="blogViewSource"
d:DesignSource="{d:DesignInstance {x:Type STESample:Blog}, CreateList=True}"/>
<CollectionViewSource
x:Key="blogPostsViewSource"
Source="{Binding Posts, Source={StaticResource blogViewSource}}"/>
</Window.Resources>
<Grid DataContext="{StaticResource blogViewSource}">
<DataGrid AutoGenerateColumns="False" EnableRowVirtualization="True"
ItemsSource="{Binding}" Margin="10,10,10,179">
<DataGrid.Columns>
<DataGridTextColumn Binding="{Binding BlogId}" Header="Id" Width="Auto" IsReadOnly="True" />
<DataGridTextColumn Binding="{Binding Name}" Header="Name" Width="Auto"/>
<DataGridTextColumn Binding="{Binding Url}" Header="Url" Width="Auto"/>
</DataGrid.Columns>
</DataGrid>
<DataGrid AutoGenerateColumns="False" EnableRowVirtualization="True"
ItemsSource="{Binding Source={StaticResource blogPostsViewSource}}" Margin="10,145,10,38">
<DataGrid.Columns>
<DataGridTextColumn Binding="{Binding PostId}" Header="Id" Width="Auto" IsReadOnly="True"/>
<DataGridTextColumn Binding="{Binding Title}" Header="Title" Width="Auto"/>
<DataGridTextColumn Binding="{Binding Content}" Header="Content" Width="Auto"/>
</DataGrid.Columns>
</DataGrid>
<Button Width="68" Height="23" HorizontalAlignment="Right" VerticalAlignment="Bottom"
Margin="0,0,10,10" Click="buttonSave_Click">Save</Button>
</Grid>
</Window>
- MainWindow (MainWindow.xaml.cs) için arkasındaki kodu açın ve içeriğini aşağıdaki kodla değiştirin
using STESample.WPFTest.BloggingService;
using System.Collections.Generic;
using System.Linq;
using System.Windows;
using System.Windows.Data;
namespace STESample.WPFTest
{
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void Window_Loaded(object sender, RoutedEventArgs e)
{
using (var service = new Service1Client())
{
// Find the view source for Blogs and populate it with all Blogs (and related Posts)
// from the Service. The default editing functionality of WPF will allow the objects
// to be manipulated on the screen.
var blogsViewSource = (CollectionViewSource)this.FindResource("blogViewSource");
blogsViewSource.Source = service.GetBlogs().ToList();
}
}
private void buttonSave_Click(object sender, RoutedEventArgs e)
{
using (var service = new Service1Client())
{
// Get the blogs that are bound to the screen
var blogsViewSource = (CollectionViewSource)this.FindResource("blogViewSource");
var blogs = (List<Blog>)blogsViewSource.Source;
// Save all Blogs and related Posts
foreach (var blog in blogs)
{
service.UpdateBlog(blog);
}
// Re-query for data to get database-generated keys etc.
blogsViewSource.Source = service.GetBlogs().ToList();
}
}
}
}
Artık uygulamayı çalıştırarak çalışır durumda görebilirsiniz.
- Çözüm Gezgini'da STESample.WPFTest projesine sağ tıklayın ve Hata Ayıkla -> Yeni örnek başlat'ı seçin
- Ekranı kullanarak verileri işleyebilir ve Kaydet düğmesini kullanarak hizmet aracılığıyla kaydedebilirsiniz