前提・実現したいこと
C# Entiry FrameworkコードファーストでWPFアプリを作成しています。
DataGridにデータを表示する際、結合しているテーブルのデータがクラス名?で表示されます。
中身のデータが表示されるようにできませんか?
そもそもDBの設計時点、データの挿入時点でよくないところがあれば指摘してください。
発生している問題・エラーメッセージ
該当のソースコード
XAML
1<Window x:Class="WpfAppTest.MainWindow" 2 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 3 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 4 xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 5 xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 6 xmlns:local="clr-namespace:WpfAppTest" 7 mc:Ignorable="d" 8 Title="MainWindow" Height="306.505" Width="408.546"> 9 <Grid> 10 <Button x:Name="btnSelect" Content="Select" HorizontalAlignment="Left" Margin="10,45,0,0" VerticalAlignment="Top" Width="75" Click="BtnSelect_Click"/> 11 <Button x:Name="btnInsert" Content="Insert" HorizontalAlignment="Left" Margin="90,45,0,0" VerticalAlignment="Top" Width="75" Click="BtnInsert_Click"/> 12 <DataGrid x:Name="dgv" HorizontalAlignment="Left" Height="186" Margin="10,70,0,0" VerticalAlignment="Top" Width="361"/> 13 14 </Grid> 15</Window>
C#
1using System; 2using System.Collections.Generic; 3using System.Linq; 4using System.Text; 5using System.Threading.Tasks; 6using System.Windows; 7using System.Windows.Controls; 8using System.Windows.Data; 9using System.Windows.Documents; 10using System.Windows.Input; 11using System.Windows.Media; 12using System.Windows.Media.Imaging; 13using System.Windows.Navigation; 14using System.Windows.Shapes; 15 16using System.Data.Entity; 17using System.ComponentModel.DataAnnotations; 18using System.ComponentModel.DataAnnotations.Schema; 19 20namespace WpfAppTest 21{ 22 public class Product 23 { 24 [Key] 25 public int ProductID { get; set; } 26 public string Name { get; set; } 27 public string Maker { get; set; } 28 public ProductCategory Category { get; set; } 29 } 30 31 public class ProductCategory 32 { 33 [Key] 34 public int CategoryID { get; set; } 35 public string CategoryName { get; set; } 36 } 37 public class StockContext : DbContext 38 { 39 public DbSet<Product> Products { get; set; } 40 public DbSet<ProductCategory> ProductCategories { get; set; } 41 } 42 43 public partial class MainWindow : Window 44 { 45 public MainWindow() 46 { 47 InitializeComponent(); 48 } 49 50 private void BtnSelect_Click(object sender, RoutedEventArgs e) 51 { 52 using (var context = new StockContext()) 53 { 54 var query = context.Products 55 .Include(a => a.Category) 56 .ToArray(); 57 58 dgv.ItemsSource = query; 59 } 60 } 61 62 private void BtnInsert_Click(object sender, RoutedEventArgs e) 63 { 64 using (var context = new StockContext()) 65 { 66 context.Products.Add(new Product 67 { 68 Name = "TestProduct", 69 Maker = "TestMaker", 70 Category = new ProductCategory { CategoryName = "TestCategory" } 71 }); 72 context.SaveChanges(); 73 } 74 } 75 } 76}
試したこと
下記サイトを参考に作成しています。
https://densan-labs.net/tech/codefirst/chapter4.html
補足情報(FW/ツールのバージョンなど)
Microsoft Visual Studio Community 2019
Entity Framework 6.2.0
8/3 16:10 追記
SurferOnWwwさんからご回答頂いた内容の通り、SelectedDataクラスを追加してBtnSelect_Clickの内容を修正したところ正常にDataGridへ値を読みだせました。
C#
1 public class SelectedData 2 { 3 public int ProductID { get; set; } 4 public string Name { get; set; } 5 public string Maker { set; get; } 6 public string CategoryName { set; get; } 7 }
C#
1 private void BtnSelect_Click(object sender, RoutedEventArgs e) 2 { 3 using (var context = new StockContext()) 4 { 5 var query = from p in context.Products.Include(a => a.Category) 6 select new SelectedData 7 { 8 ProductID = p.ProductID, 9 Name = p.Name, 10 Maker = p.Maker, 11 CategoryName = p.Category.CategoryName 12 }; 13 14 dgv.ItemsSource = query.ToArray(); 15 } 16 }
また、Entity Framework 6 Power Tools Community Editionによるグラフ化、DB生成のSQL文の確認ができました。
SQL
1create table [dbo].[Products] ( 2 [ProductID] [int] not null identity, 3 [Name] [nvarchar](max) null, 4 [Maker] [nvarchar](max) null, 5 [Category_CategoryID] [int] null, 6 primary key ([ProductID]) 7); 8create table [dbo].[ProductCategories] ( 9 [CategoryID] [int] not null identity, 10 [CategoryName] [nvarchar](max) null, 11 primary key ([CategoryID]) 12); 13alter table [dbo].[Products] add constraint [Product_Category] foreign key ([Category_CategoryID]) references [dbo].[ProductCategories]([CategoryID]);
いつもSSMSのデザイナからテーブルへの変更を加えていたのでER図?やSQL文を見るのはほぼ初めてですが、私が見たところ想定通りのDBになっているように思います。
しかしまだ気になる部分があります。
1つ目はEntity Framework, コードファーストというかっこよさげなものを使っていながらInsertとSelectでクラスを使い分けないといけない事です。これは、public ProductCategory Category { get; set; }のような書き方をやめて[ForeignKey()]などで代用して設計しなおすことで解消できるのでしょうか?(そもそもデータベースファーストを使用しろという話なのでしょうか)
2つ目はInsertしたときの挙動です。先程、想定通りのDBになっていると言ったもののProductCategiesテーブルをSSMSから確認するとCategoryNameに重複した値が書き込まれてしまっています。Entity Frameworkが勝手に判断してくれるということは無く、SQL同様に親テーブルにデータを入れておき、子テーブルに書き込むときに親テーブルのIDを使用するしかないでしょうか?
回答1件
あなたの回答
tips
プレビュー