かずきのBlog@hatena

日本マイクロソフトに勤めています。XAML + C#の組み合わせをメインに、たまにASP.NETやJavaなどの.NET系以外のことも書いています。掲載内容は個人の見解であり、所属する企業を代表するものではありません。

WCF Data Services 5.0 + Entity Framework 5.0 その2

VS2012でも使ってみた。WebApplicationを新規作成してApp_DataにEdu.sdfというファイルを追加しておく。そして、EntityFrameworkとMicrosof.Data.ServicesをNuGetから仕入れてWCF Data Servicesを新規作成して以下のような感じでコードをさくっと書きましょう。ここらへんWCF Data Services 5.0の新機能とか特に使ってないから問題ないね。

using System.Data.Entity;
using System.Data.Services;
using System.Data.Services.Common;
using System.Linq;
using System.ServiceModel.Web;

namespace OData.Education
{
    public class EduContext : DbContext
    {
        public DbSet<Person> People { get; set; }
    }

    public class Person
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public int Age { get; set; }
    }

    public class EduDataService : DataService<EduContext>
    {
        public static void InitializeService(DataServiceConfiguration config)
        {
            // とりあえずアクセスはざるで
            config.SetEntitySetAccessRule("People", EntitySetRights.All);
            config.SetServiceOperationAccessRule("*", ServiceOperationRights.All);

            config.DataServiceBehavior.MaxProtocolVersion = DataServiceProtocolVersion.V3;
        }

        // あまり意味はないけどメソッド追加
        [WebGet]
        public Person GetPersonById(int id)
        {
            return this.CurrentDataSource.People.First(p => p.Id == id);
        }

        [WebGet]
        public IQueryable<Person> GetPeople()
        {
            return this.CurrentDataSource.People;
        }
    }

}

実行してとりあえず、お約束の画面が出ることを確認しときます。


ここで、クライアント側に「Microsoft.Data.Services.Client.T4」をNuGetで入れます。リリース前のステータスなので、リリース前のパッケージも含めて検索しましょう。追加したら、メタデータの取得先を設定します。Reference.ttの42行目あたりにあるMetadataUriにWCF Data ServiceのURLに$metadataを追加したやつを設定します。

    if (string.IsNullOrEmpty(MetadataFile))
    {
        // No metadata edmx file - use a MetadataUri we were provided
        if (string.IsNullOrEmpty(MetadataUri))
        {
            MetadataUri = "http://localhost:1879/EduDataService.svc/$metadata";
        }

あと、リリース前だからか知らないけど、841行目を書き換えないと生成されたファイルがコンパイルエラーになりました。

#>        public  <#=returnType#>  <#=svcOp.Name#>(<#=parameters#>)
        {
            var enumerator =this.Execute<<#=returnType#>>(new global::System.Uri("<#= uriParameter#>",global::System.UriKind.Relative),"<#=GetServiceOperationHttpMethod(svcOp)#>",true).GetEnumerator(); // <- ここを書き換え
            enumerator.MoveNext();
            return (<#=returnType#>)enumerator.Current;
        }
<#+      

Reference.ttで生成されたファイル自体は優秀でサービス操作もばっちりタイプセーフに呼べるメソッドを作ってくれてます。こいつはいいです!!

static void Main(string[] args)
{
    var context = new EduContext(
        new Uri("http://localhost:1879/EduDataService.svc", UriKind.Absolute));

    foreach (var p in Enumerable.Range(1, 10).Select(i => new Person { Name = "aaaa " + i, Age = i + 10 }))
    {
        context.AddToPeople(p);
    }
    context.SaveChanges(SaveChangesOptions.Batch);

    foreach (var p in context.GetPeople())
    {
        Console.WriteLine(p.Name);
    }
    Console.ReadKey();
}