質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

90.86%

  • Visual Studio

    1554questions

    Microsoft Visual StudioはMicrosoftによる統合開発環境(IDE)です。多種多様なプログラミング言語に対応しています。

  • ASP.NET

    456questions

    ASP.NETは動的なWebサイトやWebアプリケーション、そしてWebサービスを構築出来るようにする為、Microsoftによって開発されたウェブアプリケーション開発フレームワークです。

  • Entity Framework

    29questions

データベースのテーブルを変更したくない

解決済

回答 2

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 536

nori0707

score 3

環境:Visual Studio 2017, ASP.NET CORE, .NET CORE, EF CORE2, SQLServer2012

既存システムのデータベースを使って、WEBアプリを作ることになりました。
今回、既存データベースに変更を加えられない状況です。

WEBアプリ用にテーブル間でリレーションをはる必要が出てきました。
この時、モデルでリレーションの書き方はわかったのですが、実行すると
データベースをマイグレーションしないと動かないとエラーになりました。

このような場合は、EntityFrameworkのFromSqlで生のSQLを発行すればいいのでしょうか?
その結果をViewに渡した時は、どのように使うのでしょうか。
この時、モデルは不要ですか?

質問ばかりになってしまってすみませんが、よろしくお願いします。


SurferOnWww様
すみません。具体的にはカレンダーマスタとその日付に紐づく情報を取得したいです。
自己解決しましたので、自己解決欄に記します。

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • SurferOnWww

    2017/11/05 10:03

    何故リレーションを張る必要が出てきたのかあたりから、具体的な例を書いてどういうことがしたいか説明できませんか?

    キャンセル

回答 2

checkベストアンサー

+1

2017/11/06 09:34 の私のコメントで「後で案を考えて書いておきます」と書きましたが、それを以下に書いておきます。

Microsoft が提供する Northwind サンプルデータベースから Visual Studio 2015 Community のウィザードを使って EF6 ベースの EDM を作り、 Products と Categories テーブルの CategoryID で内部結合と左外部結合を行うサンプルです。Core ではなく .NET Framework ベースです。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using AdventureWorksLT;
using Mvc5App.Extensions;
using System.ComponentModel.DataAnnotations;

namespace Mvc5App.Controllers
{
    public class HomeController : Controller
    {        
        private NORTHWINDEntities db = new NORTHWINDEntities();

        // 内部結合
        public ActionResult InnerJoin()
        {
            var list = from p in db.Products
                       join c in db.Categories
                       on p.CategoryID equals c.CategoryID
                       select new JoinedList
                       {
                           ProductID = p.ProductID,
                           ProductName = p.ProductName,
                           CategoryName = c.CategoryName
                       };

            return View(list);
        }

        // 左外部結合
        public ActionResult LeftOuterJoin()
        {
            var list = from p in db.Products
                       join c in db.Categories
                       on p.CategoryID equals c.CategoryID into gj
                       from subcat in gj.DefaultIfEmpty()
                       select new JoinedList
                       {
                           ProductID = p.ProductID,
                           ProductName = p.ProductName,
                           CategoryName = subcat.CategoryName ?? String.Empty
                       };

            return View(list);
        }
    }

    // Model
    // (Controller 内に定義したのは単に分けるのが面倒だったから)
    public class JoinedList
    {
        public int ProductID { set; get; }
        public string ProductName { get; set; }
        public string CategoryName { set; get; }
    }
}

LINQ で内部結合、外部結合を行う MSDN ライブラリの説明は以下の記事を見てください。 

内部結合の実行
https://docs.microsoft.com/ja-jp/dotnet/csharp/linq/perform-inner-joins

左外部結合の実行
https://docs.microsoft.com/ja-jp/dotnet/csharp/linq/perform-left-outer-joins

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/11/07 10:59

    SurferOnWww様

    回答ありがとうございます。
    今回、検索しててもEDMの例ばかりだったので、やはりEF6でそのようにしないといけないんですね。
    .NET FrameworkのMVC5はフォルダ構成がどうも好きじゃないので、できたら.NET core のMVCパターンで作成したいと思っています。
    が、DBに変更を加えられないんじゃしょうがないです。
    具体的な回答例、参考にします。
    ありがとうございました。

    キャンセル

  • 2017/11/07 15:15

    もし、フォルダ構造の好き嫌いの問題だけで Core を選択したのであれば、そこは考え直した方が良い(.NET Framework を選んだほうが良い)かもしれませんね。

    上の回答で紹介した記事の EDM は以下の記事の (1) ~ (10) の手順で作ったものを流用しています。

    スキャフォールディング機能
    http://surferonwww.info/BlogEngine/post/2017/07/23/creating-controller-and-view-in-mvc-using-scaffolding-function.aspx

    Visual Studio Community 2015 のテンプレートを使用して作った ASP.NET MVC5 プロジェクトに Visual Studio のデザイナを利用して、Northwind データベースから EDM を生成して追加してます。

    ASP.NET Core と比べてかなり単純・簡単な作業ではないでしょうか? (自分が知らないだけで、昔より Core も進化して、今は .NET と同様に簡単にできるようになっているのかもしれませんが・・・)

    キャンセル

  • 2017/11/07 19:54

    SurferOnWww様

    そうですね。フォルダ構造の好き嫌いで選んではダメですね。(笑)
    スキャフォールディングについては、提示していただいた記事を拝見しましたが、
    Coreの方は、PowerShell(NuGETコンソール)でScaffold-DbContextしたら
    簡単にモデルが作成されますので、その後、コントローラー、ビューを新規追加で自動生成ですので
    EDMが絡まないので簡単な気がします。

    キャンセル

0

モデルとデータベースのテーブルは常に一緒じゃないといけないと思っていたのですが、
既存データベースにない複数テーブルの情報を扱いたい場合、どうすればいいか解決しました。

1.コントローラーやビューで扱いたいフィールドをモデルに作成する。
ここでは、Aテーブル(Id, Date)、Bテーブル(Title, Price)が必要とする。

using System;

namespace MvcSample.Models
{
    public class CalendarList
    {
        public int Id { get; set; }
        public DateTime Date { get; set; }
        public string Title { get; set; }
        public decimal Price { get; set; }
    }
}


2.DbContextを作成する

public class CalendarListContext : DbContext
{
    public CalendarListContext(DbContextOptions<CalendarListContext> options)
        : base(options)
    { }

    public DbSet<CalendarList> CalendarLists { get; set; }
}


3.コントローラーを作成する

public class CalendarListsController : Controller
{
    private readonly CalendarListContext _context;

    public CalendarListsController(CalendarListContext context)
    {
        _context = context;
    }

    public string Index()
    {
        var results = _context.CalendarList
            .FromSql("SELECT A.Id, A.Date, B.Title, B.Price FROM table1 A LEFT OUTER JOIN table2 B ON A.Date = B.Date")
            .toList();

        if (results == null)
        {
            return NotFound();
        }

        return View(results);
    }


4.ビューを作成する

@model IEnumerable<MvcSample.Models.CalendarList>
<table>
  <tr>
    <th>Date</th>
    <th>Title</th>
    <th>Price</th>
  </tr>
    @foreach (var item in Model)
    {
      <tr>
        <td>@item.Date</td>
        <td>@item.Title</td>
        <td>@item.Price</td>
      </tr>
    }
</table>

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/11/06 09:34

    試したわけではないのでハズレだったらすみませんが・・・

    > 2.DbContextを作成する

    それは既存の DB に変更を加えないと(自動 Migration するか DB を直接いじるかはともかくとして)全体が機能しないように思われるのですが、違いますか?

    たぶん、オリジナルのテーブル A, B の Date には FK が張ってない。張ってあればナビゲーションプロパティが使えるが、張ってないので使えない・・・と言うとことから始まった話ではないかと想像しています。

    であれば、もっと簡単に、既存の EDM から LINQ で join した結果を取得できると思います。

    すみませんが今ちょっと時間が無いので、後で案を考えて書いておきます。

    キャンセル

  • 2017/11/07 10:54

    SurferOnWww様

    試した時はマイグレーションせずに試してエラーにはならなかったのですが、DbContextからDbSetを削除すると、デバッグでエラーになりました。
    その後マイグレーションすると、新しく作ったモデルのテーブルが作成されていました。
    既存テーブルが無事で、新規テーブルは作成してもいいのならありかなーと思いました。
    ただ、マイグレーションした時に、既存テーブルA,Bのモデルは不要かなと思って削除したら
    既存DBの該当テーブルA,Bが削除されましたので、既存DBへの変更を加える場合、注意しないと
    恐ろしいことになりますね。。

    キャンセル

  • 2017/11/07 13:47

    ということは解決になってないと思いますが、そうであれば解決マークは外しておいていただければと思います。

    キャンセル

  • 2017/11/07 19:57

    DB構造を変更したくないという事なら、解決には至ってないですね。
    解決マークは外しました。
    新規テーブル作成はオッケーなら、解決ということで。

    キャンセル

  • 2017/11/13 11:58

    > 新規テーブル作成はオッケーなら、解決ということで。

    新規テーブルに既存のテーブルのデータをコピーする作業が必要だと思いますが? それは質問者さんが書いたコードで自動的に面倒を見てはくれないはず。なので OK にはならないかと・・・ 違っていたら指摘ください。

    キャンセル

  • 2017/11/14 08:53

    SurferOnWww様

    新規テーブルに既存テーブルのデータをコピーしなくても、テーブルA,テーブルBからデータを取得してくれました。
    なので、この作られた新規テーブルは、アクセスされてる間どうなってるのか?謎なんですが。
    変なテーブルが複数出来るのも嫌なんで、やはり.NetFrameworkで作ってます。
    .NetCoreでできる方法があれば、引き続きよろしくお願いします。

    キャンセル

  • 2017/11/14 13:09

    > 新規テーブルに既存テーブルのデータをコピーしなくても、テーブルA,テーブルBからデータを取得してくれました。

    そうなんですか、知りませんでした。Entity Framework Core 2.0 は自分の理解のはるか上を行っているということのようです。(1.0 でもそうだったのかもしれませんが)

    > .NetCoreでできる方法があれば、引き続きよろしくお願いします。

    質問者さんの環境は、VS2017 Update 3 (Ver. 15.3) から使えるようになった ASP.NET Core 2.0, .NET Core 2.0, Entity Framework Core 2.0 と理解しています。

    残念ながら、現在自分の環境で使えるのは VS2015 Update 3 なので、お役に立てそうもありません。

    ASP.NET Core 2.0 としての質問ではなく、Entity Framework Core 2.0 の質問として、EF6 で行ったように、既存の DB から Linq を使って join して IEnumerable<T> 型のオブジェクトを取得する方法というような質問を別に立てた方が良いかもしれません。

    ところで、逆に質問して恐縮ですが、「Scaffold-DbContextしたら簡単にモデルが作成」とのことですが(質問者さんのコメントによる)、その際に EF6 と同様に .tt ファイルとそれに従属する .cs ファイルが自動生成されるということはないのでしょうか?

    キャンセル

  • 2017/11/16 21:43

    SurferOnWww様

    環境はそれで合ってます。
    .ttファイルはフォルダ内を検索してみましたが、ありませんでした。
    私はVS2008のWebフォームしか使ったことがないので、あまり理解していません。
    間違っているコメントをしているかもしれませんが、ご了承ください。
    とりあえず、今回はEF&linkで解決したということで受付を終了しますね。

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 90.86%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る

  • Visual Studio

    1554questions

    Microsoft Visual StudioはMicrosoftによる統合開発環境(IDE)です。多種多様なプログラミング言語に対応しています。

  • ASP.NET

    456questions

    ASP.NETは動的なWebサイトやWebアプリケーション、そしてWebサービスを構築出来るようにする為、Microsoftによって開発されたウェブアプリケーション開発フレームワークです。

  • Entity Framework

    29questions