根本的な解決方法を追加しました。

概要

Visual Studio 2017が更新されバージョンが15.2になりましたが、このバージョンアップを行うと、XamarinのiOSプロジェクトがビルドでエラーになります。

エラーの要点は、

  • mscorlib.dll
  • mscorlib.resources.dll

の参照が解決できないというやつです。

Mac側でビルドする際に対象となるdllの各言語対応のものが送られてないのが原因のようです。

解決方法

エラーをよく確認すると、

C:/WINDOWS/Microsoft.NET/Framework/v4.0.30319/ja/mscorlib.dll

とか、参照しに行こうとしているdllのパスがあるはずなので、まずWindows側でそのファイルを探します。そのあと、Mac側で、

/Users/(user name)/Library/Caches/Xamarin/mtbs/builds/(project name)/(uuid)/C:/WINDOWS/Microsoft.NET/Framework/v4.0.30319/ja

に、Windowsからファイルをコピーしてやればビルドが通るようになります。
ディレクトリがない場合は作ってからファイルをコピーします。

雑記

WindowsのVisualStudioをバージョンアップする前に、Mac側にVisualStudio for Macをインストールしたり、Xamarin Studioをアンインストールしたりとごちゃごちゃしてたのでそのせいかと思っていろいろ試行錯誤してたんですが、Windows版のXamarinの問題だったようです。

参考

56213 – Cannot build iOS App (Can not resolve reference: C:/Windows/Microsoft.NET/Framework/v4.0.30319/de/mscorlib.resources.dll)

のcomment 12

あるアプリのサーバー側を.NET Coreで作ってAzureにホストしているのですが、.NET Coreのバージョンを1.0から1.1にしてみました。Visual Studioは2015です。

インストール

https://www.microsoft.com/net/download/core

ここで、.NET Core 1.1 SDK – InstallerとVisual Studio 2015 Tools (Preview 2)をダウンロードしてインストール。

ファイルの書き換えとパッケージのアップデート

global.jsonのversionを書き換え。

{
  "projects": [ "src", "test" ],
  "sdk": {
    "version": "1.0.0-preview2-1-003177"
  }
}

project.jsonの下記2カ所。

"Microsoft.NETCore.App": {
  "version": "1.1.0",
  "type": "platform"
},
"frameworks": {
    "netcoreapp1.1": {

Package Manager Consoleで

PM> Update-Package

そうすると、
変更前

{
  "title": "Hoge",
  "version": "1.0.0",
  "dependencies": {
    "Microsoft.NETCore.App": {
      "version": "1.0.1",
      "type": "platform"
    },
    "Microsoft.AspNetCore.Server.IISIntegration": "1.0.0",
    "Microsoft.Extensions.Configuration.EnvironmentVariables": "1.0.0",
    "Microsoft.Extensions.Configuration.FileExtensions": "1.0.0",
    "Microsoft.Extensions.Configuration.Json": "1.0.0",
    "Microsoft.Extensions.Logging": "1.0.0",
    "Microsoft.Extensions.Logging.Console": "1.0.0",
    "Microsoft.Extensions.Logging.Debug": "1.0.0",
    "Microsoft.Extensions.Options.ConfigurationExtensions": "1.0.0",
    "Microsoft.AspNetCore.Cryptography.KeyDerivation": "1.0.0",
    "Microsoft.EntityFrameworkCore.Tools": "1.0.0-preview2-final",
    "Microsoft.AspNetCore.Mvc": "1.0.1",
    "Microsoft.AspNetCore.Server.Kestrel": "1.0.1",
    "Microsoft.EntityFrameworkCore": "1.0.1",
    "Microsoft.EntityFrameworkCore.SqlServer": "1.0.1",
    "Microsoft.AspNetCore.StaticFiles": "1.0.0"
  },
  (後略)

{
  "title": "Hoge",
  "version": "1.0.0",
  "dependencies": {
    "Microsoft.NETCore.App": {
      "version": "1.1.0",
      "type": "platform"
    },
    "Microsoft.AspNetCore.Server.IISIntegration": "1.1.0",
    "Microsoft.Extensions.Configuration.EnvironmentVariables": "1.1.0",
    "Microsoft.Extensions.Configuration.FileExtensions": "1.1.0",
    "Microsoft.Extensions.Configuration.Json": "1.1.0",
    "Microsoft.Extensions.Logging": "1.1.0",
    "Microsoft.Extensions.Logging.Console": "1.1.0",
    "Microsoft.Extensions.Logging.Debug": "1.1.0",
    "Microsoft.Extensions.Options.ConfigurationExtensions": "1.1.0",
    "Microsoft.AspNetCore.Cryptography.KeyDerivation": "1.1.0",
    "Microsoft.EntityFrameworkCore.Tools": "1.0.0-preview2-final",
    "Microsoft.AspNetCore.Mvc": "1.1.1",
    "Microsoft.AspNetCore.Server.Kestrel": "1.1.0",
    "Microsoft.EntityFrameworkCore": "1.1.0",
    "Microsoft.EntityFrameworkCore.SqlServer": "1.1.0",
    "Microsoft.AspNetCore.StaticFiles": "1.1.0"
  },
  (後略)

アップデート後は、Microsoft.EntityFrameworkCore.Tools以外は1.1.xになっています。

EntityFramework Core関連

Package Manager Consoleで

PM> Update-Package Microsoft.EntityFrameworkCore.Tools -Pre

これで、

"Microsoft.EntityFrameworkCore.Tools": "1.1.0-preview4-final"

アップデートされます。

Azureへの発行

ちょっとはまってしまったのですが、発行時にTargetFrameworkをちゃんと1.1を選んでおかないと、pubxmlの設定が1.0のままになるらしく、サーバーに発行する段階でエラーが出ます。

deploy.png

Xamarinをちょっと触っているのですが、Macを新しくしたらWindows側のXamarin Mac AgentからMacにログインできなくなりました。

20170113_macagenterror

ネットワークとかMacのSharing設定ではなく、なんかライセンスを承認してないとか言うエラーです。でもMac側では普通にXcodeも使える状態ですので調べてみたら、

Xamarin.iOS 10.0.0.6: Mac Agent can’t connect after update

Solution:

  1. Go to Xcode -> Preferences -> Location
  2. Check if “Command Line Tool” set
  3. Run sudo xcodebuild -license in terminal
  4. Follow instructions

こう言うのがあったので試してみいたら接続できるようになりました。

そういえば、Xcodeをインストールする前にCommandlineToolsを入れたような記憶があるのでそれのせいかもしれません。

タブレットで動かすWPFアプリケーションでは、ソフトウェアキーボードを制御できないので、適宜テキストボックスフォーカス時などに、c:\Program Files\Common Files\microsoft shared\ink\TabTip.exeを呼び出すようなことになります。

で、たまたまその仕組みを使っていたアプリケーションを改修していたところ、ソフトウェアキーボードが出ないようになってることに気がつきました。Anniversary Updateのせいみたいです。

調べてみたところ、HKEY_CURRENT_USER\SOFTWARE\Microsoft\TabletTip\1.7にEnableDesktopModeAutoInvokeというキーを作って、DWORD値を1にすれば良いと言うことだったので試してみたら表示されるようになりました。

Show touch keyboard (TabTip.exe) in Windows 10 Anniversary edition

Entity Frameworkは以前から興味があって、隙間を見つけてどういう風に使って、どういう風に動くのか調べてたのですが、途切れ途切れになったままCoreになってしまったので、また試してみました。

大体データベースを扱う場合は、何らかデータがリレーションしていたりして、親子になってるテーブルなんかは普通に出てきます。そういうのを単純なモデルにするとこうなります。

public class Order
{
    public int OrderId { get; set; }
    public DateTime OrderDate { get; set; }

    public List<OrderDetail> OrderDetails { get; set; }
}

public class OrderDetail
{
    public int OrderDetailId { get; set; }
    public stirng ProductCode { get; set; }
    public int Amount { get; set; }

    public int OrderId { get; set; }
    public Order Order { get; set; }
}

これで、Order-OrderDetailで親子になるようなテーブルができてくれます。
データをセットするときは、

var context = SampleDbContext();

context.Order.Add(
    new Order
    {
        OrderDate = DateTime.Now,
        OrderDetails = new List<OrderDetails>
        {
            new OrderDetail
            {
                ProductCode = "A001",
                Amount = 1
            }
        }
    });

context.SaveChanges();

こんな感じで普通にC#でオブジェクトを扱うようにすれば、よしなにしてくれます。
データを取得する場合は、

var context = SampleDbContext();

var orders = context.Orders;

foreach (var order in orders)
{
    Console.WriteLine($"{order.OrderId},{order.OrderDate}");
    foreach (var detail in order.OrderDetails)
    {
        Console.WriteLine($"{detail.ProductCode},{detail.Amount}");
    }
}

とかやると、もうSQLのことを何も考えず、JOINとか気にする必要なくデータが出る……と思いきや、order.OrderDetailsの中身がnullになっててエラーになります。
前やってみたときはこれでさくっと出て、いたく感動したものですが、なんか思った通りに行きません。モデルもきわめて単純だし、データをのぞいてみてもちゃんと入ってるのに……

で、回答はここにありました。

Part 2. Entity Framework Core 1.0 の基本的な使い方

こちらの下の方にある「Lazy Loadingの廃止」というところが参考になりました。

前に行けていたように思えていたのは、Lazy LoadingでEFがあとから引っ張ってきてくれていたおかげなんですね。

var orders = context.Orders
    .Include(o => o.OrderDetails);

こうすると子のデータも取れるようになりました。
もしOrderDetailがさらにリストを持っているような場合は、

var orders = context.Orders
    .Include(o => o.OrderDetails)
        .ThenInclude(d => d.DetailSubItems);

みたいに、ThenIncludeをつないでいくことになります。

また、Orderが複数のリストを持つような場合は、

var orders = context.Orders
    .Include(o => o.OrderDetails)
        .ThenInclude(d => d.DetailSubItems)
    .Include(o => o.Items);

みたいにして、Includeを繋げれば取ってこれます。

Entity Frameworkについてはググると以前のバージョンについての話と、Coreについての話がぱっと見てわかりづらいのでなかなか調べるのもなかなか大変ですね。

« Prev Next »