Übersetzung vorschlagen
 
Andere Vorschläge:

progress indicator
Keine anderen Vorschläge
MSDN Magazin > Home > Ausgaben > 2009 > MSDN Magazin Mai 2009 >  Auf die Daten mit ADO.NET Data Services auf lok...
Inhalt anzeigen:  Englisch mit deutscher ÜbersetzungInhalt anzeigen: Englisch mit deutscher Übersetzung
Dies sind maschinell übersetzte Inhalte, die von den Mitgliedern der Community bearbeitet werden können. Sie können die Übersetzung verbessern, indem Sie auf den jeweils zum Satz gehörenden Link "Bearbeiten" klicken.Mithilfe des Dropdown-Steuerelements "Inhalt anzeigen" links oben auf der Seite können Sie zudem bestimmen, ob nur der englische Originaltext, nur die deutsche Übersetzung oder beides nebeneinander angezeigt werden.
Data Services
Access Your Data On Premise Or In The Cloud With ADO.NET Data Services
Elisa Flasko
Code download available from the MSDN Code Gallery
Browse the Code Online

This article is based on prerelease versions of Windows Azure and ASP.NET MVC.

This article discusses:
  • Windows Azure
  • ASP.NET MVC
  • Windows Azure Table
  • On-Premise vs Cloud app development
This article uses the following technologies:
Windows Azure, ASP.NET MVC
Web Services has been a hot topic for a number of years now, but what, you may wonder, are these Data Services everyone's talking about lately? As the architecture of Web applications has changed and matured (with the popularity of Rich Internet Applications [RIAs], for example), there has been an increased awareness of the value of exposing raw data, minus any interface or formatting, to any service or application that wants to consume it. Data Services are simple data-centric services with a RESTful interface, that do exactly that—expose pure data for consumption by applications. Such services expose data using a uniform interface to be consumed by Web clients across a corporate intranet or the Internet. Data Services can be built and hosted on your premises using the ADO.NET Data Services Server Library to expose data securely as a service, or may be made available by various hosted services such as Windows Azure Table. Windows Azure is the foundation of the Microsoft Cloud Platform. As the "operating system for the cloud" it provides the essential building blocks you need to write scalable and highly available services. A major part of Azure, Windows Azure Table, allows users to persist data in the cloud and expose the data it stores as a Data Service.
Regardless of where the data service is hosted, the ADO.NET Data Services framework provides a set of Client Libraries built for a range of Microsoft Development platforms (.NET, Silverlight, ASP.NET AJAX, and so on) that allow you to easily consume these services in your applications.

Figure 1 Entity Data Model Exposed by the Micro-Blogging Data Service
The Application
Throughout this article, I will be building a simple Micro-Blogging application using ASP.NET Model View Controller (MVC) (release candidate) and will detail some of the typical scenarios that arise when building such services-based applications. I'll assume a prior understanding of MVC and will therefore not discuss the specifics of this pattern. If you need more information about ASP.NET MVC, see the ASP.NET MCV site . For the purpose of comparison, I will look at two versions of the same basic application—one consuming an on-premises Data Service, and one consuming an Azure Table Data Service. The code for both versions is included in the accompanying code download.
The Micro-Blogging application allows users to post messages to specific channels, create new channels, and view messages on the channels of interest to them. The model that has been exposed by the Data Service for this application consists of three types of entities: Messages, Channels, and Users, with a largely one-to-one mapping to the database. It is worth noting at this point, that with an on-premises data source, this model does contain a first-class notion of relationships between entities. Messages are posted to a particular Channel by an individual User (see Figure 1).

Consuming an On-Premises Data Service with the ADO.NET Data Services Client Library
Let's begin by creating a new ASP.NET MVC Web Application using the Visual Studio template installed with ASP.NET MVC.
There are two primary ways that you could go about defining the classes to represent the model on the client. You could simply define the model by defining the POCO (Plain Old CLR Objects) classes that will be used on the client to represent the entities exposed by the service, which I will do when I develop this application against Windows Azure Table, or you could use the Add Service Reference Wizard in Visual Studio to generate the necessary classes. As when you use Add Service Reference for a Windows Communication Foundation (WCF) service, you simply right-click on the Project and choose Add Service Reference. In the Add Service Reference dialog box, enter the URI for the entry point of the service as the Address, and then click OK. This will generate the associated classes, based on the data service definition, and add them to the project.
As seen in Figure 2, the Add Service Reference Wizard has generated a class for each of my Entities: Channel, Message, and User, as well as a class representing the service as a whole—microblogEntities. The class microblogEntities inherits from DataServiceContext and will be used as the starting point for access to the data service.
Figure 2 Classes Representing Micro-Blogging Model

Querying Data
With the app now set up to access the data service, I can start developing the remainder of my application. On the homepage, the application will provide a listing of the available Channels and allow the user to view today's messages by selecting a Channel. The user will also be able to filter within that Channel based on Author. To create the homepage, I will need to create an ActionResult in the Home controller that will map to the Index view (the Home controller and Index view are created by default in the MVC template). On the homepage, I will need to retrieve a listing of all available Channels from the data service, as well query the service for today's messages, filtering based on user input (see Figure 3).
Figure 3 Site HomePage
The ADO.NET Data Service Client Library allows you to easily query data with the use of language integrated query (LINQ), as you see in Figure 4 .
The Index action of the homepage controller is called by the MVC application when the homepage is accessed by the browser and returns the data that will be used to render the Index.aspx view. In Figure 4, inside the Index action, I instantiate a new instance of the DataServiceContext microblogEntities, like so:
microblogEntities svc = new microblogEntities(new Uri("http://localhost:50396/MicroData.svc"));
public ActionResult Index(string channel, string author)
    {
        microblogEntities svc = new microblogEntities(new 
        Uri("http://localhost:50396/MicroData.svc"));
        ViewData["channels"] = svc.Channels;

        int y = DateTime.Now.Year;
        int mm = DateTime.Now.Month;
        int d = DateTime.Now.Day;

        var q = from m in svc.Messages.Expand("Author").Expand("Channel")
                where m.Channel.ChannelName == channel && (m.DatePosted.Year == y && 
                m.DatePosted.Month == mm && m.DatePosted.Day == d)
                select m;

        if (!string.IsNullOrEmpty(author))
        {
            q = from m in q
                where m.Author.UserName == author
                select m;
        }

        ViewData["msg"] = q;

        return View();
    }
This is the object that I will use every time I want to hit the service. The first query that will be executed against the Data Service accesses all of the Channels available. The second, a LINQ query, retrieves all of the Messages in the channel that was requested when the user hit the page and filters by author if a name was provided. Note that in the provided sample code, messages are viewed by entering the Channel Name and, if desired, the Author name into the text box and then clicking View. It is also worth noting that the queries require a ChannelName; and a search cannot be executed by author name alone. I place both of the aforementioned queries into ViewData to be executed as the page is rendered and then return.
Now, in the view for the homepage, Index.aspx, I will actually enumerate over the queries, effectively executing the query against the store at this point, and will then print the results to the page (see Figure 5 ).
<h2>Today's Messages</h2>
    <form action="./">
        Channel:<span style="color: #FF0000">*</span> <input type="text" 
            name="channel" 
            />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
            Author: <input type="text" name="author" /><br />
        <input type="submit" value="Search" />
    </form> 
    <ul>
    <!-- Execute query placed in ViewData["msg"] - enumerates over 
        results and prints resulting message data to the screen -->
    <% foreach (var m in (Ienumerable
        <MicroBloggingOnPremise.Models.Message>)
    ViewData["msg"])
       { %>
    <li><%=m.Author.UserName%>@<%=m.DatePosted %>: <%=m.Text%> 
        [<%=m.Channel.ChannelName %>]</li>
    <%} %>
    </ul>



    <h2>Channels</h2>
    <ul>
    <!-- Execute query placed in ViewData["channels"] - enumerates over 
         results and prints resulting channel data to the screen -->
        <% foreach (var channel in 
        (IEnumerable<MicroBloggingOnPremise.Models.Channel>)
            ViewData["channels"])
           { %>

          <li><%=channel.ChannelName %> (<%=channel.DateCreated %>)</li>

        <% } %>
    </ul>

Create, Update, and Delete
To create a new entity instance in the data service using the ADO.NET Data Service Client Library, I create a new instance of the .NET object that represents the entity set and call the AddTo… method for the Entity Set on the DataServiceContext instance that I'm using, passing the new object and the entity set that I am adding it to.
For example, let's look at the PostMessage action of the homepage controller, in Figure 6 , which is called when I attempt to post a message by clicking the Send button.
[AcceptVerbs("POST")]
        public ActionResult PostMessage(string channel, string author, 
            string msg)
        {
            microblogEntities svc = new microblogEntities(new 
            Uri("http://localhost:50396/MicroData.svc"));

            Channel chan = (from c in svc.Channels
                    where c.ChannelName == channel
                    select c).FirstOrDefault();


            if (chan == null) throw new ArgumentException("Invalid 
                channel");

            User u = (from auth in svc.Users
                     where auth.UserName == author
                     select auth).FirstOrDefault();

            if (u == null) //throw new ArgumentException("Invalid 
                Author");
            {
                //To simplify this example we will create a new user, 
                //if the user was null when we queried. 
                //It is possible that another client creates 
                //the same UserName 
                //before we call SaveChanges() 
                //and we end up with 2 Users with the same name
                var user = new User();
                user.UserName = author;
                user.DateCreated = DateTime.UtcNow;
                svc.AddToUsers(user);
                u = user;

            }


            var m = new Message();

            m.DatePosted = DateTime.UtcNow;
            m.Text = msg;
            svc.AddToMessages(m);
            svc.SetLink(m, "Channel", chan);
            svc.SetLink(m, "Author", u);

            try
            {
                svc.SaveChanges();
            }
            catch (Exception e)
            {
                throw (e);
            }
            return this.RedirectToAction("Index");
        }
Notice that the method is decorated with the AcceptVerbs("POST") attribute, since we're using it for a form post. Again I start by instantiating a new DataServiceContext as the entry point to my service and then I query for the specified channel to check that it exists. If the channel does not exist, I throw an exception; otherwise, I create a new Message passing in the data entered by the user. Once the Message has been created, I need to tell the context that I have a new object to be added by calling svc.AddToMessages(m); passing in the new Message object, m. I also set links representing the relationships attached to this new message, in this case svc.SetLink(m, "Channel", chan); associating the message with the specified Channel and svc.SetLink(m, "Author", u); associating the message with the specified Author. Finally, I want to push the changes to the service and into the database by calling svc.SaveChanges();.
If I were modifying an existing instance rather than creating a new one, I would first query for the object that I want to update, make the desired changes, and rather than AddToMessages, I would call the UpdateObject method to indicate to the context that it needs to send an update for that object the next time I call SaveChanges(). Similarly, if I were deleting an instance, once I had the object, I would call the Delete method to indicate to the context that I want to delete that object.
In this example, and so far in this article, you have seen a single operation on the client map to a single HTTP request being sent to the service. In many scenarios, it is also beneficial for the client to be able to batch a group of operations and send them to the service in a single HTTP request. This reduces the number of round trips to the service and enables a logical scope of atomicity for sets of operations. The ADO.NET Data Service Client Library supports sending a group of Insert, Update, and/or Delete operations to a service in a single HTTP request via a call to the SaveChanges() method, passing SaveChangesOptions.Batch as the only parameter. This parameter value instructs the client to batch all pending changes into a single HTTP request sent to the service. By sending changes as a batch, you ensure that either all the changes will complete successfully or none of the changes will be applied.

Consuming an Azure Table Data Service
When you are developing a .NET application using Windows Azure Table, the data is accessed using the ADO.NET Data Services client libraries. In this section, I will walk through the development of the same simple application used above, but this time I will be accessing and manipulating data stored in Azure Table. For the remainder of this article, I assume that a Windows Azure Storage account has already been set up and is available for your use. For more information on getting started with Windows Azure Table, see the Azure Services Platform Developer Center .

The Azure Table Data Model
Before getting started on an application, there are a couple things that you must know about the Azure Table Data Model for best performance. An application may choose to create many tables within a storage account where each table contains a set of Entities (rows) and each Entity contains a set of Properties (columns). Each Entity is able to have up to 255 properties, stored as <Name, TypedValue> pairs and is identified using two key properties that together become the unique ID. This first key property is the PartitionKey (type string), enabling partitioning for scalability, and the other is the RowKey (also type string), uniquely identifying the entity within the partition. Beyond the two key properties, there is no fixed schema for the remaining properties, meaning that the application is responsible for enforcing any schema that must be maintained.
One of the important differences when developing against Windows Azure Table compared to local database storage surrounds partitioning. With Azure Table, the application controls the granularity of partitions, and partitioning becomes very important to both the performance and scalability of the application. This means that the choice of the PartitionKey property is very important, and impacts performance because the table clusters entities (Entity Locality) with the same partition key value. To choose the best PartitionKey possible, you should choose the key such that it is common to the majority (or all) of the queries used in the application. Performance and scalability can also be impacted similarly by the number of partitions used by the application (number of different values in the PartitionKey); having more partitions allows the server to better balance the load across nodes.

The ADO.NET Data Services Client Library
Now I will build the same Micro-Blogging application, using ASP.NET Mode View Controller (MVC), and this time I will detail some of the questions that typically arise when building applications against data stored in Windows Azure Table.
Similar to my on-premises database, this will require three Entities in my model, which I will translate into three Tables: a Messages table, a Channels table, and a Users table, all set up in my storage account.
Throughout the application I will make use of the StorageClient sample that ships within the Windows Azure SDK. The StorageClient sample implements a library you can use to access the Windows Azure blob storage service, queue service, and the table storage service. I will use the library to help me access the table storage service. The Windows Azure SDK can be downloaded from the Azure Services Platform Developer Center cited earlier.
To begin, I will create a new ASP.NET MVC Web Application using the Visual Studio template installed with ASP.NET MVC, and add the StorageClient project from the Windows Azure SDK to the solution.

Defining the Model on the Client
The first step in building the application is to define the classes that will be used on the client to represent the entities exposed by the service. Since Azure Table does not have a fixed schema, I cannot use the Add Service Reference Wizard as I did with the on-premises service. However, as I mentioned above, I can create my own POCO classes. These classes will effectively be used to define the schema for the application, as Azure Table does not enforce any schema on the server side. I will define a Message class, a Channel class, and a User class to align with the EntityTypes exposed by the service. To begin, I add a new code file, MicroData.cs, to the Models folder where I will define my classes. These classes will be defined in the MicroBloggingAzure.Models namespace.
If you take a look at the Messages class shown in Figure 7, you can see that I have defined both a PartitionKey and a RowKey, as required by Azure Table. This is a departure from what you saw in the on-premises service because they are specific to Windows Azure Table. It is worth noting that the best practices for key determination are not recommended across Relational and Cloud storage, and in my sample applications I have used the most appropriate key determination for each data source rather than trying to align the two in any way. The PartitionKey and RowKey are simply defined as type string and identified using naming conventions (that is, calling them PartitionKey and RowKey). In the case of this application, the PartitionKey is made up of the name of the Channel to which the message is posted, concatenated with an "@" and the date the message was posted in the format "yyyy-mm-dd". The RowKey is a string representation of the date that the message was posted. This PartitionKey was chosen such that the application can efficiently retrieve messages that were recently posted to a particular channel. To begin with, I have chosen to show only today's posts when a channel is accessed; however, if my application becomes very popular and receives thousands of posts a day, this key can be easily modified to partition more granularly— for example, by adding in a time component (hour perhaps). Similarly, if my application is not as busy as anticipated, I could modify the PartitionKey to partition by month rather than by day. I have then identified the two key properties as a uniquely identifying DataServiceKey, which is done by adding the DataServiceKey attribute to the class. The Messages class also defines a number of other properties containing information about the message, a part of the required keys. All of the properties associated with the Message entity will be stored in Azure Table. The User and Channel classes are created following the same principles as the Message class.
[DataServiceKey("PartitionKey", "RowKey")]
    public class Message
    {
        // ParitionKey is channel name [+ day]
        public string PartitionKey { get; set; }
        // Date/Time when the message was created
        public string RowKey { get; set; }

        public string Text { get; set; }
        public string Author { get; set; }
        public string Channel { get; set; }
        public DateTime DatePosted { get; set; }
        public int Rating { get; set; }

        public Message()
        {
        }

        public Message(string channel, string author, string text)
        {
            this.Text = text;
            this.Author = author;
            this.Channel = channel;
            this.DatePosted = DateTime.UtcNow;

            this.PartitionKey = MakeKey(this.Channel, this.DatePosted);
            this.RowKey = System.Xml.XmlConvert.ToString(
               this.DatePosted);
        }
        public static string MakeKey(string channel, DateTime dt)
        {
            return channel + "@" + dt.ToString("yyyy-MM-dd");
        }
    }

Creating a Table
Once my entity classes have been defined, I can begin really developing the application. But first, I need to add my Azure Table Account access information to Web.config, as seen here:
<appSettings>
  <add key="TableStorageEndpoint"        value="http://table.core.windows.net/"/>
  <add key="AccountName" value="<MyAccountName>"/>
  <add key="AccountSharedKey" value="<MyAccountSharedKey-Provided when        you register for Azure Tables>"/>
</appSettings> 
Although this is not the only way of passing account information when developing against Azure Table, this will allow me to use the Azure SDK to automatically pick up my account settings and deal with connections to the data source.
Often in applications written against Windows Azure Table, the creation of tables required by the app is done programmatically within the application. This is a little different from how one would normally do things with an on-premises data store, where the tables are created separately in the database and the application simply interacts with them.
One way of creating the required tables programmatically would be to simply create a new Entity in the master table called Tables. Every table that you create in your storage account must be represented as an entity in the master table, which is predefined when you register your account. For this application, however, I will use the StorageClient, which provides functionality to check, upon application initialization, that the required Tables exist in the storage account, and if they do not exist, will create them.
By creating the tables programmatically within the application, I simplify the process by which I can reflect updates to the model in the data store. For example, if down the road I add the ability for a user to subscribe to a channel, and add a subscription entity to the model, the associated table will automatically be added to the data store the next time the application starts. This choice also ensures that if the app is distributed for use with different Azure Tables accounts, all the user needs to do is to enter his or her account access information and the tables are correctly set up and ready for use when the application is run.
If you have existing data already in Azure Table, or if you do not have control over the tables in Azure, you may skip the step of creating tables altogether and simply program against your existing tables.
To check and create the tables in my application, I will use the TableStorage.CreateTablesFromModel() method that is a part of the StorageClient library, as seen here:
protected void Application_Start()
{
       RegisterRoutes(RouteTable.Routes); //MVC Routing Rules

       TableStorage.CreateTablesFromModel (typeof(Models.MicroData));
}  

Querying Data
With my app set up to access my account in Azure Tables, the remainder of it works just as if I were accessing an on-premises service. Just as with my on-premises service, since I'm using the ADO.NET Data Service Client Library, I am able to easily work with my data as .NET objects and to query it using LINQ (see Figure 8).
public ActionResult Index(string channel, string author)
        {
            var svc = new Models.MicroData();
            ViewData["channels"] = svc.Channels;

            var q = from m in svc.Messages
                    where m.PartitionKey == Models.Message.
                       MakeKey(channel, DateTime.UtcNow)
                    select m;
            if (!string.IsNullOrEmpty(author))
            {
                q = from m in q
                    where m.Author == author
                    select m;
            }

            ViewData["msg"] = q;

            return View();
        }
In Figure 8, you see the Index action of the homepage controller. Inside this action, I instantiate a new instance of my DataServiceContext (MicroData inherits from TableStorageDataServiceContext), the object I use to access the service, and write the queries to be executed against the Data Service. I then retrieve a listing of all available Channels from the data service and write the LINQ query to retrieve all of Today's Messages, filtering based on user input (Channel and possibly Author if provided). I place both queries into ViewData to be executed as the page is rendered and then return. Notice that the pattern here is the same as when I accessed the on-premises data source; I instantiate a new DataServiceContext instance and query using simple LINQ queries against my model.
In the view for my homepage (Index.aspx in Figure 9 ), I enumerate over my queries, executing the queries against the store, and print the results to the page.
<h2>Today's Messages</h2>
    <form action="./">
        Channel:<span style="color: #FF0000">*</span> <input type="text" 
        name="channel" /><br />
        Author: <input type="text" name="author" /><br />
        <input type="submit" value="View" />
    </form> 
    <ul>
    <!-- Execute query placed in ViewData["msg"] - enumerates over 
         results and prints resulting message data to the screen -->
    <% foreach (var m in (IEnumerable<MicroBloggingAzure.Models.Message>)
       ViewData["msg"])
       { %>
    <li><%=m.Author%>@<%=m.DatePosted %>: <%=m.Text%> [<%=m.Channel %>]
    </li>
    <%} %>
    </ul>


   <h2>Channels</h2>

    <ul>
    <!-- Execute query placed in ViewData["channels"] - enumerates over 
    Results and prints resulting channel data to the screen -->
        <% foreach (var channel in 
        (IEnumerable<MicroBloggingAzure.Models.Channel>)
        ViewData["channels"])
        { %>

          <li><%=channel.PartitionKey %> (<%=channel.DateCreated %>)</li>

        <% } %>
       </ul>

Create, Update, and Delete
Creating a new entity in the table service using the ADO.NET Data Service Client Library, just as if I were working against an on-premises store, is done by creating a new instance of the .NET object that represents the entity set and calling AddObject().
Let's look at the PostMessage action of my homepage controller, in Figure 10 .
[AcceptVerbs("POST")]
        public ActionResult PostMessage(string channel, string author, string msg)
        {
            var svc = new Models.MicroData();

            var q = from c in svc.Channels
                    where c.PartitionKey == channel
                    select c;

            if (q.FirstOrDefault() == null) throw new
            ArgumentException("Invalid channel");

            User u = (from auth in svc.Users
                     where auth.UserName == author
                     select auth).FirstOrDefault();

            if (u == null)
            //throw new ArgumentException("Invalid Author");
            {
                var user = new User();
                user.UserName = author;
                user.DateCreated = DateTime.UtcNow;
                user.PartitionKey = user.UserName;
                user.RowKey = string.Empty;
                svc.AddObject("Users", user);
                u = user;
            }

            var m = new Models.Message(channel, author, msg);
            svc.AddObject("Messages", m);

            svc.SaveChanges();

            return this.RedirectToAction("Index");
        }
Just as I did to query the data service, I instantiate a new DataServiceContext as the entry point and query for the specified channel to check that it exists, throwing an exception if it is not found. I create a new Message, passing in the user input. Once the Message has been created, I tell the context that I have a new object to be added by calling svc.AddObject("Messages", m); passing in the EntitySet name that I am adding to, "Messages", and new Message object, m. Finally, I want to push the changes into the Table service by calling svc.SaveChanges();.
There are a couple of differences that you may notice here. The first is due to the lack of a fixed schema in Azure Table. This lack of schema means that I do not have strongly typed data and must call the untyped AddObject() on the DataServiceContext instance, passing the new object and the entity set that I am adding it to, rather than the typed AddTo…() methods that I used against my on-premises store. It is worth noting here that the more generic AddObject() method is still available in the on-premises scenario; however, in my example I use the strongly typed methods to take advantage of compile-time checking and so forth.
The second difference, also somewhat attributed to the lack of fixed schema, is the lack of a first-class relationship concept. You first notice this in the differences between how I structure the data in Azure Table compared to my on-premises data source. In the PostMessage action you'll notice that I am not setting links on my new object; rather, any relationship information is stored directly as properties in my Entities.
If I were modifying an existing instance rather than creating a new one, I would first query for the object that I want to update, make the desired changes and, finally, rather than AddObject, I would call the UpdateObject method to indicate to the context that it needs to send an update for that object the next time I call SaveChanges(), just as I would with an on-premises data service. Similarly, deleting an instance by calling the Delete method to indicate to the context that I want to delete that object, is also the same whether I am accessing an Azure Table service or my own on-premises service.

Summing Up
Looking at these two examples together, you can see how simple the move between developing against an on-premise service and an Azure Table service is made by the use of the same simple ADO.NET Data Services Client Library. The learning curve involved is rather flat if you are also responsible for managing each data source and mostly consists of a shift in thinking between the relational storage model and the more unstructured Azure Table model, as well as an awareness of the Azure Table PartitionKey and RowKey model. If you are focused primarily on the application development against these services, the skills you build up developing against one service are transferable to development against any other data service.

Elisa Flasko is a Program Manager in the Data Programmability team at Microsoft, including the ADO.NET technologies, XML technologies, and SQL Server Connectivity technologies. She can be reached at blogs.msdn.com/elisaj .

Data Services
Zugriff auf Ihre Daten auf lokale oder in der Wolke mit ADO.NET Data Services
Elisa Flasko

Dieser Artikel basiert auf Vorabversionen von Windows-Azure und ASP.NET (MVC).

In diesem Artikel werden die folgenden Themen behandelt:
  • Windows-Azure
  • ASP.NET (MVC)
  • Windows Azure-Tabelle
  • Zur-lokale-vs Wolke Anwendung Entwicklung
In diesem Artikel werden folgende Technologien verwendet:
Windows-Azure, ASP.NET (MVC)
web Services wurde ein hot Thema für eine Anzahl von Jahren jetzt, aber was, Sie können Fragen, sind diese Datendienste jeder sprechen ist in letzter Zeit? Als die Architektur von Web-Anwendungen wurde geändert und matured (mit der Beliebtheit von Rich-Internet-Anwendungen [RIAs], z. B.), es hat eine erhöhte Bewusstsein des Werts Offenlegen von Rohdaten, minus jede Schnittstelle oder wurde Formatierung, auf alle Dienst- oder, möchte es nutzen. Data Services sind einfache datenzentrischer-Dienste mit einer RESTful-Schnittstelle, die genau dies tun, reine Daten für die Nutzung von Anwendungen verfügbar zu machen. Solche Dienste verfügbar machen, Daten mithilfe von eine einheitliche Schnittstelle und von Web-clients über ein Firmenintranet oder das Internet genutzt werden sollen. Data Services können erstellt und auf Ihre Gelände mit ADO.NET Data Services-Serverbibliothek Daten sicher als Dienst gehostet oder möglicherweise werden verfügbar gemacht durch verschiedene gehostete Dienste wie Windows-Azure-Tabelle. Windows-Azure ist es sich um die Grundlage der der Microsoft-Plattform Wolke. Als "Betriebssystem für die Wolke" bietet es die wesentlichen Bausteine, die Sie skalierbar und hoch verfügbaren Dienste schreiben müssen. Ein wichtiger Teil Azure, Windows-Azure-Tisch, ermöglicht Benutzern das Beibehalten von Daten in der Wolke und verfügbar machen die Daten als Dienst Daten gespeichert.
Unabhängig davon, in dem der Datendienst befindet bietet das ADO.NET Data Services-framework, eine Reihe von Client-Server für einen Bereich von Microsoft Development Plattformen (.NET, Silverlight, ASP.NET AJAX usw.) erstellt, die Sie einfach diese Dienste in Ihren Anwendungen nutzen können.

Abbildung 1 Entity Data Model vom Dienst Micro-Blogs Daten freigegeben werden
Die Anwendung
In diesem Artikel ich eine einfache Micro-Blogs-Anwendung mithilfe von ASP.NET Model View Controller (MVC) (release candidate) erstellen und Details Teil der typischen Szenarios, die auftreten, wenn diese Dienste-basierte Anwendungen zu erstellen. Es wird eine vorherige Kenntnis MVC wird davon ausgegangen, und die Einzelheiten der dieses Muster nicht daher diskutieren wird. Falls Sie weitere Informationen zu ASP.NET (MVC) benötigen, finden Sie die ASP.NET-MCV-Website . Zum Zweck der Vergleich es sieht in zwei Versionen der gleichen grundlegenden Anwendung, eine die verbraucht ein Dienst auf dem Gelände Daten und eine der verbraucht ein Azure Tabelle Data Service. Der code für beide Versionen ist in der zugehörigen Codedownload enthalten.
Die Anwendung Micro-Blogs ermöglicht Benutzern das Bereitstellen von Nachrichten auf bestimmte Kanäle, erstellen neue Kanäle und Anzeigen von Nachrichten in den Kanälen für Sie von Interesse. Das Modell, das vom Dienst Daten für diese Anwendung besteht aus drei Arten von Entitäten ausgesetzt wurde: Nachrichten Kanäle und Benutzer mit einer zum überwiegenden Teil 1: 1-Zuordnung in die Datenbank. Es ist zu diesem Zeitpunkt Beachten Sie, dass der dieses Modell mit einer auf dem Gelände Datenquelle, ein wesentlicher Konzept von Beziehungen zwischen Entitäten enthalten sind. Nachrichten werden durch einen einzelnen Benutzer zu einem bestimmten Kanal gebucht (siehe Abbildung 1 ).

Verbraucht ein On Premises Data Service mit der Daten mit ADO.NET Services Client Library
Betrachten wir zunächst Erstellen einer neuen ASP.NET MVC von Anwendung mit der Visual Studio-Vorlage mit ASP.NET MVC installiert.
Es gibt zwei primäre Möglichkeiten, die Sie zum Definieren von Klassen zur Darstellung von des Modell auf dem client verlaufen können. Sie können einfach das Modell definieren, indem definieren die POCO (Plain Old CLR Objects)-Klassen, die zum Darstellen von der Entitäten, die durch den Dienst, der ich wird beim Entwickeln von dieser Anwendung für Windows-Azure-Tisch, verfügbar gemacht werden auf dem client verwendet wird, oder Sie konnte des Assistenten zum Hinzufügen von Service Referenz in Visual Studio verwenden, um die erforderlichen Klassen zu generieren. B. Hinzufügen eines Dienstverweises für einen Dienst Windows Communication Foundation (WCF) Sie einfach mit der rechten Maustaste auf das Projekt und Hinzufügen eines Dienstverweises auswählen. Das Dialogfeld Hinzufügen eines Dienstverweises Geben Sie den URI für den Einstiegspunkt des Dienstes als die Adresse, und klicken Sie dann auf OK. Dadurch wird zugeordneten Klassen, basierend auf die Daten Dienstdefinition erstellen und diese dem Projekt hinzufügen.
Wie in Abbildung 2 dargestellt hat Service Reference Assistenten für eine Klasse für jede der Einheiten generiert: Kanal, Nachricht, und Benutzer sowie eine Klasse, die den Dienst als Ganzes darstellt, microblogEntities. Die Klasse microblogEntities erbt DataServiceContext und wird als Ausgangspunkt für den Zugriff auf den Datendienst verwendet werden.
Abbildung 2 Klassen Darstellung Micro-Blogs-Modell

Abfragen von Daten
Mit der Anwendung eingerichtet können auf den Datendienst zugreifen ich starten den Rest der meine Anwendung entwickeln. Auf der homepage wird die Anwendung, geben eine Liste der verfügbaren Kanäle und der Benutzer zum Anzeigen der heutigen Nachrichten durch Auswählen eines Kanals kann. Der Benutzer darüber hinaus werden in filtern, dass die Channel auf Stufe 4 basiert. Um die homepage zu erstellen, müssen ich eine ActionResult in den Start-controller zu erstellen, das die Index-Ansicht zugeordnet wird (der Start-controller und die Index-Ansicht werden standardmäßig in der MVC-Vorlage erstellt). Auf der homepage, wird es müssen, um eine Liste aller verfügbaren Kanäle aus den Datendienst zu abzurufen, sowie der Abfrage den Dienst für die heutigen Nachrichten filtern basierend auf Benutzereingaben (siehe Abbildung 3 ).
Abbildung 3 -Website-HomePage
Die ADO.NET Data Service-Client-Bibliothek können Sie einfach Abfragen von Daten mithilfe von language integrated query (LINQ), wie Sie in sehen Abbildung 4 .
Die Index-Aktion des homepage-Controllers ist von der MVC-Anwendung aufgerufen, wenn der homepage vom browser erfolgt, und es gibt die Daten, die verwendet werden soll, um die Index.aspx-Ansicht gerendert zurück. In Abbildung 4 , in der Aktion Index ich instanziieren eine neue Instanz des DataServiceContext-microblogEntities, wie folgt:
microblogEntities svc = new microblogEntities(new Uri("http://localhost:50396/MicroData.svc"));
public ActionResult Index(string channel, string author)
    {
        microblogEntities svc = new microblogEntities(new 
        Uri("http://localhost:50396/MicroData.svc"));
        ViewData["channels"] = svc.Channels;

        int y = DateTime.Now.Year;
        int mm = DateTime.Now.Month;
        int d = DateTime.Now.Day;

        var q = from m in svc.Messages.Expand("Author").Expand("Channel")
                where m.Channel.ChannelName == channel && (m.DatePosted.Year == y && 
                m.DatePosted.Month == mm && m.DatePosted.Day == d)
                select m;

        if (!string.IsNullOrEmpty(author))
        {
            q = from m in q
                where m.Author.UserName == author
                select m;
        }

        ViewData["msg"] = q;

        return View();
    }
Dies ist das Objekt, das ich jedem Drücken Sie den Dienst soll verwendet werden. Die erste Abfrage, die für die Data-Dienst ausgeführt werden greift auf aller die Kanäle zur Verfügung. Das zweite, einer LINQ-Abfrage, werden alle für die Nachrichten im Kanal, der angefordert wurde, wenn der Benutzer die Seite und die Filter nach Autor Wenn ein name angegeben wurde abgerufen. Beachten Sie, dass im Beispielcode bereitgestellten Nachrichten angezeigt werden durch Eingabe des Namens-Kanal und, falls gewünscht, den Autor-Namen in das Textfeld und dann auf Anzeigen. Es ist auch beachten, dass die Abfragen ein Kanalname erfordern; und eine Suche nicht werden, indem Namen des Autors allein ausgeführt kann. Ich Platzieren der oben genannten Abfragen in ViewData ausgeführt werden, wie die Seite gerendert wird, und zurückgeben.
Nun, in der Ansicht für die homepage, Index.aspx, es wird tatsächlich Aufzählen über die Abfragen, effektiv Abfrage für den Informationsspeicher zu diesem Zeitpunkt ausgeführt und wird dann die Ergebnisse auf der Seite (Siehe Drucken Abbildung 5 ).
<h2>Today's Messages</h2>
    <form action="./">
        Channel:<span style="color: #FF0000">*</span> <input type="text" 
            name="channel" 
            />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
            Author: <input type="text" name="author" /><br />
        <input type="submit" value="Search" />
    </form> 
    <ul>
    <!-- Execute query placed in ViewData["msg"] - enumerates over 
        results and prints resulting message data to the screen -->
    <% foreach (var m in (Ienumerable
        <MicroBloggingOnPremise.Models.Message>)
    ViewData["msg"])
       { %>
    <li><%=m.Author.UserName%>@<%=m.DatePosted %>: <%=m.Text%> 
        [<%=m.Channel.ChannelName %>]</li>
    <%} %>
    </ul>



    <h2>Channels</h2>
    <ul>
    <!-- Execute query placed in ViewData["channels"] - enumerates over 
         results and prints resulting channel data to the screen -->
        <% foreach (var channel in 
        (IEnumerable<MicroBloggingOnPremise.Models.Channel>)
            ViewData["channels"])
           { %>

          <li><%=channel.ChannelName %> (<%=channel.DateCreated %>)</li>

        <% } %>
    </ul>

Erstellen Sie, Aktualisieren und Löschen
Um eine neue Instanz der Entität im Datendienst mithilfe der ADO.NET Data Service-Client-Bibliothek zu erstellen, ich eine neue Instanz des .NET Objekts, das den Satz Entität darstellt, erstellen und rufen Sie die AddTo…-Methode für die Entität-Gruppe in der DataServiceContext-Instanz, die ich bin verwenden, übergeben Sie das neue Objekt und, wenn die Entität festlegen, dass ich es hinzufügen bin.
Beispielsweise sehen wir uns die PostMessage Aktion des homepage-Controllers in Abbildung 6 , das heißt, bei dem Versuch, eine Nachricht bereitstellen, indem Sie auf die Schaltfläche " Senden " klicken.
[AcceptVerbs("POST")]
        public ActionResult PostMessage(string channel, string author, 
            string msg)
        {
            microblogEntities svc = new microblogEntities(new 
            Uri("http://localhost:50396/MicroData.svc"));

            Channel chan = (from c in svc.Channels
                    where c.ChannelName == channel
                    select c).FirstOrDefault();


            if (chan == null) throw new ArgumentException("Invalid 
                channel");

            User u = (from auth in svc.Users
                     where auth.UserName == author
                     select auth).FirstOrDefault();

            if (u == null) //throw new ArgumentException("Invalid 
                Author");
            {
                //To simplify this example we will create a new user, 
                //if the user was null when we queried. 
                //It is possible that another client creates 
                //the same UserName 
                //before we call SaveChanges() 
                //and we end up with 2 Users with the same name
                var user = new User();
                user.UserName = author;
                user.DateCreated = DateTime.UtcNow;
                svc.AddToUsers(user);
                u = user;

            }


            var m = new Message();

            m.DatePosted = DateTime.UtcNow;
            m.Text = msg;
            svc.AddToMessages(m);
            svc.SetLink(m, "Channel", chan);
            svc.SetLink(m, "Author", u);

            try
            {
                svc.SaveChanges();
            }
            catch (Exception e)
            {
                throw (e);
            }
            return this.RedirectToAction("Index");
        }
Beachten Sie, dass die Methode mit dem Attribut AcceptVerbs("POST") ergänzten Windows ist, da wir es für ein Formular-post verwenden. Erneut starten durch Instanziieren einen neuen DataServiceContext als Eintrag zeigen Sie auf meinen Dienst, und es dann Abfragen für den angegebenen Kanal ein, um zu überprüfen, dass es vorhanden ist. Wenn der Kanal nicht vorhanden ist, löst es eine Ausnahme; andernfalls ich erstellen, eine neue Nachricht, die vom Benutzer eingegebenen Daten übergeben. Nachdem die Nachricht erstellt wurde, ich möchte dem Kontext mitteilen, besteht ein neues Objekt durch Aufrufen svc.AddToMessages(m); hinzugefügt werden in das neue Message-Objekt übergeben m. Auch festgelegt Hyperlinks, die die Beziehungen dieser neuen Nachricht, in diesem Fall-svc.SetLink(m, "Channel", chan) zugeordnet darstellt des angegebenen Kanal und svc.SetLink(m, "Author", u) die Nachricht zugeordnet; der angegebene Autor die Nachricht zugeordnet. Schließlich möchte ich die Änderungen an den Dienst und in die Datenbank übertragen durch Aufrufen von svc.SaveChanges();.
Wenn ich wurden eine vorhandene Instanz ändern, sondern eine neue zu erstellen, es würde zuerst Abfragen für das Objekt, das ich aktualisieren möchten nehmen die gewünschten Änderungen vor, und anstatt AddToMessages, ich Sie die UpdateObject-Methode rufen würde, um den Kontext anzuzeigen, dass es ein update für das Objekt das nächste Mal senden muss rufe ich die SaveChanges(). Ebenso Wenn ich eine Instanz des löschen wurden nach der das Objekt war, würde ich rufen Sie die löschen Methode um zum Kontext anzugeben, dass ich dieses Objekt gelöscht werden sollen.
In diesem Beispiel, und bisher in diesem Artikel haben Sie einem Vorgang auf der Karte client und einem einzelnen HTTP-Anforderung an den Dienst gesendet gesehen. In vielen Szenarios ist es auch hilfreich für den client Lage Stapelverarbeitung eine Gruppe von Vorgängen und senden Sie an den Dienst in einer einzelnen HTTP-Anforderung. Dies verringert die Anzahl von Roundtrips, mit dem Dienst und einer logischen Umfang Atomarität für Gruppen von Vorgängen ermöglicht. Die ADO.NET Data Service-Client-Bibliothek unterstützt, senden eine Gruppe von Insert, Update, und/oder Löschen-Vorgänge auf einen Dienst in einer einzigen HTTP-Anforderung über einen Aufruf der Methode SaveChanges() SaveChangesOptions.Batch als des einzigen Parameters übergeben. Dieser Parameterwert weist es sich um den client an, alle ausstehende Änderungen in einer einzelnen HTTP-Anforderung, die an den Dienst gesendet batch. Durch das Senden von Änderungen als batch, sicherstellen, dass alle Änderungen erfolgreich abgeschlossen werden oder keine der Änderungen angewendet werden wird.

Verwenden einen Azure-Tabelle Data Service
Bei Sie eine .NET-Anwendung mit der Windows-Azure-Tabelle Entwicklung sind werden die Daten Zugriff verwendet die ADO.NET Data Services-client-Bibliotheken. In diesem Abschnitt ich durch die Entwicklung der gleichen einfache Anwendung über verwendet durchlaufen wird, aber diesmal ich wird werden beim Zugriff auf und Bearbeiten von Daten in der Azure-Tabelle gespeichert. Für den Rest dieses Artikels angenommen es, dass ein Windows-Azure-Speicher-Konto bereits eingerichtet wurde und für die steht. Weitere Informationen in Erste Schritte mit Windows-Azure-Tabelle finden Sie unter der Azure Services-Plattform Developer Center .

Das Azure-Tabelle-Datenmodell
Vor dem Einstieg in einer Anwendung, sind es ein paar Dinge, die Sie dem Azure-Tabelle-Datenmodell für eine optimale Leistung kennen müssen. Eine Anwendung kann entscheiden viele Tabellen in einem Speicher-Konto, in dem jede Tabelle enthält eine Reihe von Entitäten (Zeilen) und jede Entität enthält eine Reihe von Eigenschaften (Spalten). Jede Entität-kann bis zu 255 Eigenschaften aufweisen, als < Name, TypedValue > Paare gespeichert und wird identifiziert mit zwei wichtige Eigenschaften, die zusammen die eindeutige ID werden Diese erste wichtige Eigenschaft ist die PartitionKey (Typ Zeichenfolge), Aktivieren Partitionierung für Skalierbarkeit und der andere RowKey (auch Typ Zeichenfolge), die die Entität in der partition eindeutig identifiziert. Über die zwei wichtigen Eigenschaften besteht kein festen schema für die übrigen Eigenschaften, d. h., dass die Anwendung, ist für das vorgeben alle Schemas, die gewartet werden muss, verantwortlich.
Die wichtigsten Unterschiede bei der Entwicklung für Windows Azure Tabellen im Vergleich zu lokalen Datenbank Speicherplatz eines umgibt Partitionierung. Mit Azure-Tabelle die Anwendung steuert die Granularität von Partitionen und Partitionierung wird sehr wichtig, für die Leistung und die Skalierbarkeit von der Anwendung. Dies bedeutet, dass die Auswahl der PartitionKey-Eigenschaft sehr wichtig ist und wirkt sich auf Leistung, da die Tabelle Entitäten (Entität Ort)-Cluster mit dem gleichen Schlüsselwert der partition. Am besten verfügbaren PartitionKey auswählen möchten, sollten Sie den Schlüssel wählen, dass es in den meisten (oder alle) der Abfragen in der Anwendung verwendet. Leistung und Skalierbarkeit können auch werden beeinträchtigt entsprechend durch die Anzahl der Partitionen, die von der Anwendung (Anzahl der unterschiedliche Werte in der PartitionKey) verwendet, müssen weitere Partitionen ermöglicht dem server eine bessere Saldo die Last über Knoten hinweg.

Der ADO.NET Data Services-Client-Bibliothek
Jetzt ich wird Erstellen der gleichen Anwendung Micro-Blogs mithilfe von ASP.NET Modus View Controller (MVC) und dieses Mal wird ich einige der Fragen, die normalerweise auftreten, beim Erstellen von Anwendungen mit Daten aus der Windows-Azure-Tabelle beschrieben.
Ähnlich wie bei meiner Datenbank auf dem Gelände, dies benötigen drei Einheiten in der ich den Übersetzen in drei Tabellen werden Modell: einer Nachrichten-Tabelle, eine Kanäle-Tabelle und einer Tabelle Benutzer alle in mein Speicher-Konto eingerichtet.
In der gesamten Anwendung ich wird nutzen von der StorageClient Beispiele, die in das Windows-Azure-SDK enthalten ist. Das StorageClient-Beispiel implementiert eine Bibliothek, die mit der Windows Azure-blob-Speicherdienst, Warteschlange-Dienst und der Speicherdienst Tabelle zugreifen. Es verwendet die Bibliothek, zum nützlich in der Tabelle Speicher-Dienst zugreifen. Das Windows-Azure-SDK kann aus dem Azure Services-Plattform Developer Center oben angegebenen gedownloadet werden.
Um zu beginnen, ich erstellen eine neue ASP.NET MVC-Webanwendung mit der Visual Studio-Vorlage mit ASP.NET MVC installiert, und fügen Sie das StorageClient-Projekt aus dem Windows-Azure-SDK zur Lösung hinzu.

Definieren das Modell auf dem Client
Das erste Schritt beim Erstellen der Anwendung ist die Klassen definieren, die auf dem client verwendet werden soll, um die Einheiten, die durch den Dienst verfügbar gemacht werden darstellen. Da Azure-Tabelle keinem festen schema vorhanden ist, kann nicht es des Assistenten zum Hinzufügen von Service Referenz verwenden, wie ich mit dem Dienst auf dem Gelände. Wie bereits oben erwähnt, kann es jedoch eigene POCO-Klassen erstellen. Diese Klassen werden effektiv verwendet definieren Sie das schema für die Anwendung, wie Azure-Tabelle keine schema auf der Serverseite erzwungen wird. Es wird eine Message-Klasse, einer Channel-Klasse und einer Benutzerklasse an die EntityTypes, die durch den Dienst verfügbar gemacht werden ausgerichtet definieren. Um zu beginnen, fügen es eine neue Codedatei, MicroData.cs, Sie zum Ordner Modelle in dem ich meine Klassen definieren wird. Diese Klassen werden im MicroBloggingAzure.Models-namespace definiert.
Wenn Sie einen Blick auf die Nachrichten-Klasse in Abbildung 7 gezeigte ergreifen, können Sie sehen, dass ich sowohl eine PartitionKey und eine RowKey, als erforderlich nach Azure-Tabelle definiert haben. Dies ist ein Wechsel von was Sie haben im Dienst auf dem Gelände gesehen da Sie speziell für Windows-Azure-Tabelle. Es ist zu beachten, dass die bewährten Methoden zum Schlüssel ermitteln nicht über die relationale und Wolke Speicher sollten und in meinem Beispielanwendungen haben ich die am besten geeignete Schlüssel Ermittlung für jede Datenquelle verwendet, sondern die beiden in irgendeiner Weise ausrichten möchten. Die PartitionKey und die RowKey sind einfach als Typ Zeichenfolge definiert und identifizierten verwenden Namenskonventionen (, die Sie PartitionKey und RowKey anrufen,) ein. Im Fall von dieser Anwendung die PartitionKey besteht aus den Namen des Kanals, die Nachricht gebucht werden, verkettet mit " wurde ein @" sowie das Datum, an die Nachricht im format bereitgestellt" jjjj-mm-tt ". Die RowKey handelt es sich um das Datum, das die Nachricht bereitgestellt wurde eine Zeichenfolgendarstellung. Diese PartitionKey wurde ausgewählt, so, dass die Anwendung effizient Nachrichten abrufen kann, die auf einem bestimmten Kanal vor kurzem gebucht wurden. Zunächst ich haben ausgewählt, nur aktuelle Beiträge anzuzeigen Wenn auf ein Kanal zugegriffen wird, jedoch Wenn meine Anwendung sehr beliebte wird und Tausende von Beiträgen Tag empfängt, dieser Schlüssel kann problemlos geändert werden auf partition mehr granularly, z. B. durch Hinzufügen von in einer Zeit-Komponente (Stunde vielleicht). Ebenso ist meine Anwendung nicht als gebucht, als der erwarteten, konnte ich die PartitionKey auf partition Monat anstatt nach Tagen ändern. Ich haben dann die beiden wichtigsten Eigenschaften ein eindeutig identifizierenden DataServiceKey, festgestellt der durchgeführt wird, indem Sie das DataServiceKey-Attribut in der Klasse. Die " Nachrichten "-Ereignisklasse definiert auch eine Reihe von anderen Eigenschaften mit Informationen über die Nachricht, einen Teil der erforderlichen Schlüssel. Alle Eigenschaften der Nachricht Entität zugeordnet werden in Azure-Tabelle gespeichert. Die Klassen Benutzer und -Kanal werden nach die gleichen Prinzipien wie die Message-Klasse erstellt.
[DataServiceKey("PartitionKey", "RowKey")]
    public class Message
    {
        // ParitionKey is channel name [+ day]
        public string PartitionKey { get; set; }
        // Date/Time when the message was created
        public string RowKey { get; set; }

        public string Text { get; set; }
        public string Author { get; set; }
        public string Channel { get; set; }
        public DateTime DatePosted { get; set; }
        public int Rating { get; set; }

        public Message()
        {
        }

        public Message(string channel, string author, string text)
        {
            this.Text = text;
            this.Author = author;
            this.Channel = channel;
            this.DatePosted = DateTime.UtcNow;

            this.PartitionKey = MakeKey(this.Channel, this.DatePosted);
            this.RowKey = System.Xml.XmlConvert.ToString(
               this.DatePosted);
        }
        public static string MakeKey(string channel, DateTime dt)
        {
            return channel + "@" + dt.ToString("yyyy-MM-dd");
        }
    }

Erstellen einer Tabelle
Sobald die Entität-Klassen definiert haben, kann ich beginnen, wirklich Entwicklung der Anwendung. Aber zunächst ich muss meine Azure Tabelle Konto Zugriff Web.config, hinzufügen wie hier dargestellt:
<appSettings>
  <add key="TableStorageEndpoint"        value="http://table.core.windows.net/"/>
  <add key="AccountName" value="<MyAccountName>"/>
  <add key="AccountSharedKey" value="<MyAccountSharedKey-Provided when        you register for Azure Tables>"/>
</appSettings> 
Obwohl dies nicht die einzige Methode der Kontoinformationen zu übergeben, bei der Entwicklung mit Azure-Tabelle ist, wird dies zulassen Verwenden des Azure-SDK zu automatisch Kontoeinstellungen übernehmen befassen sich mit der Verbindungen mit der Datenquelle.
Häufig wird in Anwendungen mit Windows-Azure-Tabelle geschrieben, die Erstellung von der Anwendung erforderlichen Tabellen programmgesteuert in der Anwendung abgeschlossen. Dies unterscheidet sich ein wenig vom wie eine Umgang mit einem auf dem Gelände Datenspeicher, gewohnt wobei die Tabellen separat in der Datenbank erstellt und die Anwendung einfach interagiert, mit.
Eine Möglichkeit zum Erstellen der erforderlichen Tabellen würde programmgesteuert zum Erstellen eine neue Entität einfach in der Mastertabelle Tabellen aufgerufen werden. Jede Tabelle, die Sie in Ihrem Konto Speicher erstellen muss als eine Entität in der Tabelle " master " dargestellt werden, die nicht vordefiniert ist, wenn Sie Ihr Konto registrieren. Für diese Anwendung jedoch ich verwenden der StorageClient, die Funktionalität zum Initialisierungszeitpunkt Anwendung überprüfen, die die erforderlichen Tabellen in dem das Konto Speicher enthalten sein bereitstellt und diese nicht vorhanden sind, erstellt werden.
Erstellen Sie die Tabellen programmgesteuert in der Anwendung, vereinfachen ich mit dem ich updates für das Modell im Datenspeicher wiedergeben können. Z. B. wenn unten der Straße ich die Möglichkeit für Benutzer abonnieren einen Kanal hinzufügen, und das Modell eine Entität Abonnement hinzugefügt, wird die zugehörige Tabelle automatisch an den Datenspeicher das nächste Mal hinzugefügt, das der Anwendung starten. Mit dieser Option wird auch gewährleistet, dass, wenn die Anwendung wird mit den verschiedenen Azure Tabellen Konten verteilt, der Benutzer muss dazu seinem Konto Zugriffsinformationen eingeben und die Tabellen sind richtig eingerichtet und für die Verwendung bereit, wenn die Anwendung ausgeführt wird.
Wenn vorhandene Daten in Azure-Tabelle noch oder wenn Sie keine Kontrolle über die Tabellen in Azure verfügen, können Sie überspringen die Schritt Tabellen ganz zu erstellen und einfach Programmieren für die vorhandenen Tabellen.
Um zu prüfen und erstellen Sie die Tabellen in meiner Anwendung, wird es die TableStorage.CreateTablesFromModel()-Methode verwenden, die einen Teil der StorageClient-Bibliothek zu ist, wie hier dargestellt:
protected void Application_Start()
{
       RegisterRoutes(RouteTable.Routes); //MVC Routing Rules

       TableStorage.CreateTablesFromModel (typeof(Models.MicroData));
}  

Abfragen von Daten
Mit der Anwendung, die für mein Konto in Azure-Tabelle zugreifen eingerichtet funktioniert die restlichen, nur wie wenn ich einen Dienst auf dem Gelände Zugriff auf wurden. Genau wie mit der Dienst auf dem Gelände da ich die ADO.NET Data Service-Client Bibliothek, verwende ich können problemlos mit meine Daten als Objekte mit .NET arbeiten und mit LINQ Abfragen (siehe Abbildung 8 ).
public ActionResult Index(string channel, string author)
        {
            var svc = new Models.MicroData();
            ViewData["channels"] = svc.Channels;

            var q = from m in svc.Messages
                    where m.PartitionKey == Models.Message.
                       MakeKey(channel, DateTime.UtcNow)
                    select m;
            if (!string.IsNullOrEmpty(author))
            {
                q = from m in q
                    where m.Author == author
                    select m;
            }

            ViewData["msg"] = q;

            return View();
        }
In Abbildung 8 erfahren Sie, den Index Aktion des homepage-Controllers. In diesem Aktion, instanziieren ich eine neue Instanz der DataServiceContext (MicroData erbt vom TableStorageDataServiceContext), das Objekt ich verwenden, um den Dienst zuzugreifen, und schreiben Sie die Abfragen für die Data-Dienst ausgeführt werden. ICH dann Abrufen von eine Liste aller verfügbaren Kanäle aus den Datendienst und schreiben, die LINQ-Abfrage aller heutige Nachrichten, Filtern, basierend auf den Benutzereingabe (Channel und möglicherweise Autor, wenn angegeben) abrufen. Ich setzen die beiden Abfragen in ViewData ausgeführt werden, wie die Seite gerendert wird, und zurückgeben. Beachten Sie, dass hier das Muster identisch ist mit, wenn ich die Datenquelle auf dem Gelände darauf zugreifen, sondern ich eine neue DataServiceContext Instanz instanziieren und einfache LINQ-Abfragen für meine Modell Abfragen.
In der Ansicht für meine homepage (Index.aspx-in Abbildung 9: ), Ich Aufzählen über Meine Abfragen, Ausführen der Abfragen für den Informationsspeicher und die Ergebnisse auf der Seite zu drucken.
<h2>Today's Messages</h2>
    <form action="./">
        Channel:<span style="color: #FF0000">*</span> <input type="text" 
        name="channel" /><br />
        Author: <input type="text" name="author" /><br />
        <input type="submit" value="View" />
    </form> 
    <ul>
    <!-- Execute query placed in ViewData["msg"] - enumerates over 
         results and prints resulting message data to the screen -->
    <% foreach (var m in (IEnumerable<MicroBloggingAzure.Models.Message>)
       ViewData["msg"])
       { %>
    <li><%=m.Author%>@<%=m.DatePosted %>: <%=m.Text%> [<%=m.Channel %>]
    </li>
    <%} %>
    </ul>


   <h2>Channels</h2>

    <ul>
    <!-- Execute query placed in ViewData["channels"] - enumerates over 
    Results and prints resulting channel data to the screen -->
        <% foreach (var channel in 
        (IEnumerable<MicroBloggingAzure.Models.Channel>)
        ViewData["channels"])
        { %>

          <li><%=channel.PartitionKey %> (<%=channel.DateCreated %>)</li>

        <% } %>
       </ul>

Erstellen Sie, Aktualisieren und Löschen
Erstellen eine neue Entität im Dienst Tabelle mithilfe von ADO.NET Data Service-Client Bibliothek, nur wie Wenn gegen einen Speicher auf dem Gelände bearbeiteten erfolgt durch Erstellen einer neuen Instanz des .NET Objekts, das den Satz Entität darstellt und Aufrufen von AddObject().
Werfen wir einen Blick auf die PostMessage Aktion des Meine homepage-Controllers in Abbildung 10 .
[AcceptVerbs("POST")]
        public ActionResult PostMessage(string channel, string author, string msg)
        {
            var svc = new Models.MicroData();

            var q = from c in svc.Channels
                    where c.PartitionKey == channel
                    select c;

            if (q.FirstOrDefault() == null) throw new
            ArgumentException("Invalid channel");

            User u = (from auth in svc.Users
                     where auth.UserName == author
                     select auth).FirstOrDefault();

            if (u == null)
            //throw new ArgumentException("Invalid Author");
            {
                var user = new User();
                user.UserName = author;
                user.DateCreated = DateTime.UtcNow;
                user.PartitionKey = user.UserName;
                user.RowKey = string.Empty;
                svc.AddObject("Users", user);
                u = user;
            }

            var m = new Models.Message(channel, author, msg);
            svc.AddObject("Messages", m);

            svc.SaveChanges();

            return this.RedirectToAction("Index");
        }
Nur wie ich um den Datendienst zu Abfragen, instanziiert eine neue DataServiceContext als Einstiegspunkt und Abfrage für die angegebene Kanal überprüfen, ob er vorhanden ist, eine Ausnahme auslösen, wenn es nicht gefunden wird. Es erstellt eine neue Nachricht, in die Benutzereingabe übergeben. Sobald die Nachricht erstellt wurde, erkennen ich den Kontext, die ich ein neues Objekt durch Aufrufen von svc.AddObject ("Nachrichten, m) hinzugefügt werden; die EntitySet name, der es hinzugefügt am "Nachrichten" Neue Nachricht-Objekt, und m übergeben. Schließlich möchte ich die Änderungen durch Aufrufen von svc.SaveChanges(); in den Tabellen-Dienst zu übertragen.
Es sind einige der Unterschiede, die Sie hier feststellen können. Der erste ist aufgrund von fehlenden eines festen Schemas in Azure-Tabelle. Dieser Mangel schema bedeutet, dass es keine stark typisierte Daten und müssen Aufrufen der nicht typisierte AddObject() auf der DataServiceContext-Instanz übergeben das neue Objekt und die Entität, dass ich es, Hinzufügen am, festgelegt anstatt die eingegebenen AddTo…()-Methoden, die ich für meine auf Gelände zu verwendet, speichern. Es handelt sich hier Beachten Sie, dass die allgemeine AddObject()-Methode noch verfügbar ist, in dem Szenario auf dem Gelände ist; allerdings in meinem Beispiel ich verwenden die stark typisierten Methoden Kompilierungszeit überprüft und so weiter nutzen.
Der zweite Unterschied, ist die Mangels an feste schema auch etwas zugeordnet, die fehlende ein wesentlicher Beziehung Konzept. Sie bemerken zuerst diese zu den Unterschieden zwischen wie ich die Daten in Azure-Tabelle im Vergleich zu der Datenquelle auf dem Gelände strukturieren. In der PostMessage Aktion Sie sehen, bin ich auf meine neue Objekt nicht links festlegen, vielmehr wird keine Beziehung Informationen gespeichert, direkt als Eigenschaften in der Entitäten.
Wenn es wurden ändern eine vorhandene Instanz von statt eine neue zu erstellen, es würde zuerst für das Objekt, das ich möchte aktualisieren, nehmen Sie die gewünschten Änderungen vor und Abfragen, schließlich statt AddObject, würde ich rufen Sie die UpdateObject-Methode, um auf den Kontext anzuzeigen, dass eine Aktualisierung für dieses Objekt das nächste Mal, das ich SaveChanges(), aufrufen, gesendet, wie ich mit dem ein Dienst auf dem Gelände Daten werden muss. Ebenso entspricht Löschen einer Instanz durch Aufrufen der Delete-Methode, um zum Kontext anzugeben, dass ich dieses Objekt gelöscht werden sollen, auch, ob es einen Azure-Tabelle-Dienst oder eigene Dienst auf dem Gelände zugreift bin.

Addieren von
Betrachten diese beiden Beispiele miteinander aus, wird können Sie wie einfache das Verschieben zwischen für einen Dienst unter der Voraussetzung entwickeln und ein Azure-Tabelle-Dienst durch die Verwendung der gleichen einfache ADO.NET Daten Services Client Bibliothek. Die Einarbeitung beteiligt ist, eher flache, wenn Sie auch zum Verwalten der einzelnen Datenquellen verantwortlich sind, und hauptsächlich besteht eine Schicht in Denken zwischen dem relationalen Speicher-Modell und das mehr unstrukturierten Azure-Tabelle-Modell sowie ein Bewusstsein des Modells Azure Tabelle PartitionKey und RowKey aus. Wenn Sie hauptsächlich auf die Anwendungsentwicklung mit diesen Diensten konzentrieren, dann sind die Fertigkeiten, die Sie, erstellen Sie entwickeln, die für einen Dienst zur Entwicklung für alle anderen Daten Dienste übertragbar.

Elisa-Flasko ist Program Manager im Daten-Programmierbarkeit-team bei Microsoft, einschließlich der ADO.NET Technologien, XML-Technologien und SQL Server-Remotekonnektivität-Technologien. Sie können unter erreichen blogs.msdn.com/elisaj .

Page view tracker