かずきのBlog@hatena

すきな言語は C# + XAML の組み合わせ。Azure Functions も好き。最近は Go 言語勉強中。日本マイクロソフトで働いていますが、ここに書いていることは個人的なメモなので会社の公式見解ではありません。

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();
}