🎄teratailクリスマスプレゼントキャンペーン2024🎄』開催中!

\teratail特別グッズやAmazonギフトカード最大2,000円分が当たる!/

詳細はこちら
Entity Framework

Entity Frameworkは、.NET Framework 3.5より追加されたデータアクセス技術。正式名称は「ADO.NET Entity Framework」です。データベースエンジンに依存しておらず、データプロバイダの変更のみで様々なデータベースに対応できます。

.NET Core

.NET Coreは、マネージソフトウェアフレームワークでオープンソースで実装されています。クロスプラットフォームを前提に考えられており、Windows/Mac/Linuxで動くアプリケーションを作成することが可能です。

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

WPF

Windows Presentation Foundation (WPF) は、魅力的な外観のユーザー エクスペリエンスを持つ Windows クライアント アプリケーションを作成するための次世代プレゼンテーション システムです

Q&A

解決済

1回答

3619閲覧

[C#][WPF][EF]Entity Framework で DB にアクセスする際コンテキストのオブジェクトが自動的に注入されるよう DI 機能を WPF アプリに実装したい

neko_usagi

総合スコア10

Entity Framework

Entity Frameworkは、.NET Framework 3.5より追加されたデータアクセス技術。正式名称は「ADO.NET Entity Framework」です。データベースエンジンに依存しておらず、データプロバイダの変更のみで様々なデータベースに対応できます。

.NET Core

.NET Coreは、マネージソフトウェアフレームワークでオープンソースで実装されています。クロスプラットフォームを前提に考えられており、Windows/Mac/Linuxで動くアプリケーションを作成することが可能です。

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

WPF

Windows Presentation Foundation (WPF) は、魅力的な外観のユーザー エクスペリエンスを持つ Windows クライアント アプリケーションを作成するための次世代プレゼンテーション システムです

0グッド

0クリップ

投稿2020/08/24 07:29

編集2020/08/24 08:43

前提・実現したいこと

はじめまして。
最近、独学でプログラムとC#を勉強し始めた者です。
.Net Core + EF Core + Prism + ReactivePropertyを使用して、
一気に勉強できたらなと思い挑戦しています。

今回は、SQLServerに接続する際に毎度usingを記載するのが、
視覚的に読みづらくなると個人的に思い、改善したく質問させていただきます。

自分で調べた結果、ASP.Net CoreではDIコンテナを使用した方法があると知り、
同じような形でできないかと挑戦しましたが、どう実装していいのか。
お力を借りたく存じます。

環境

.Net Core 3.1
EF Core 3.1.7
Prism Core 7.2.0

ソースコード

現状のソースコードを貼ります。

App.xaml.cs

namespace TempWpfApp { /// <summary> /// Interaction logic for App.xaml /// </summary> public partial class App { protected override Window CreateShell() => Container.Resolve<MainWindow>(); protected override void RegisterTypes(IContainerRegistry container) { container.RegisterForNavigation<HomeView>(); } protected override void OnInitialized() { base.OnInitialized(); Container.Resolve<IRegionManager>().RequestNavigate("MainRegion", nameof(HomeView)); } } }

HomeViewModel.cs

namespace TempWpfApp.ViewModels { class HomeViewModel { private HomeModel model = new HomeModel(); public HomeViewModel() { this.model = new HomeModel(); this.Input.Value = this.model.Input; } public ReactivePropertySlim<string> Input { get; } = new ReactivePropertySlim<string>(); } }

HomeModel.cs

namespace TempWpfApp.Models { class HomeModel: BindableBase { public HomeModel() { // ここを改善したい using (var db = new DataContext()) { // データを取得(Inputにデータ挿入) } } private string input = "Home"; public string Input { get { return input; } set { SetProperty(ref input, value); } } } }

DataContext.cs

namespace TempWpfApp.Database { public class DataContext : DbContext { public DbSet<User> User { get; set; } protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) { optionsBuilder.UseSqlServer(new DbConnection().GetConnectionString()); } } }

試したこと

ASP.Net Coreではstartup.csに以下を記述することで、
HomeViewModelを呼んだ際にDIコンテナがDataContextを自動で注入してくれるとのことでした。
しかし、.Net CoreではConfigureServices(IServiceCollection services)をどこで呼べばいいのか、
HomeViewModelではinterfaceでないからダメと問題が多発しました。

startup.cs

public void ConfigureServices(IServiceCollection services) { services.AddDbContext<DataContext>(options => { options.UseSqlServer("接続文字列"); }); }
public class HomeViewModel { readonly DataContext _dataContext ; public HomeViewModel(DataContext dataContext ) { _dataContext = dataContext ; } ... }

補足情報

質問以外の部分でも、修正した点がよい箇所が有りましたら、
指摘いただければと思います。
よろしくお願いいたします。

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

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

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

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2020/08/24 08:32

タイトルの「SQLServerにusingを使わずに接続したい」は適切ですかね? やりたいことは using 句を使わないではなくて、「Entity Framework で DB にアクセスする際コンテキストのオブジェクトが自動的に注入されるよう DI 機能を WPF アプリに実装したい」ではないのですか?
neko_usagi

2020/08/24 08:41

おっしゃる通りです。 using~はとっかかり部分なので、タイトルには不適切でした。変更させていただきます。指摘ありがとうございます!
hihijiji

2020/08/24 10:27

その環境なら拡張機能の"Prism Template Pack"が便利です。 それの中のPrism Full App(.Net Core)ってテンプレートにDIを利用した雛形が入ってます。 DbContextを隠蔽したServiceを作って、そのServiceをDIに放り込んでおいて HomeModelではそれを利用する形がかっこいいかと思います。
neko_usagi

2020/08/24 12:03

hihijiji様 コメントありがとうございます。早速試してみたのですが、質問させてください。 >DbContextを隠蔽したServiceを作って 新たにIDataServiseというinterfaceを作成し、DataContextに継承させた結果、エラーが出てしまいました。以下、エラー文 --- CS0535 'DataContext' はインターフェイス メンバー 'IDataContext.DataContext' を実装しません。 --- エラー内容は分かるのですが、どう対処していいかわかりません。 IDataServise.cs ``` public interface IDataService { DataContext DataContext { get; } } ``` IDataServise.csの定義方法がおかしいのでしょうか。 理解力なく、大変申し訳ございません、教えていただけないでしょうか。
hihijiji

2020/08/25 01:06

インターフェイスにDataContext DataContext { get; }を書かないで、 代わりのメソッドなりプロパティなりを実装したら如何でしょう?
neko_usagi

2020/08/26 10:58

hihijiji様 仕事都合で返信遅れ申し訳ないです。 アドバイス通り、なんとか実装ができました! ありがとうございます。
guest

回答1

0

自己解決

hihijiji様からのアドバイスを頂き、なんとか実装まではたどり着けました。
ありがとうございます。

当初は、ViewModel[~ViewModel.cs] ← Model[~Model.cs] のように考えていましたが、
今回、View[~ViewModel.cs] ← Model[Service.cs ← Context.cs]
のようにModel部分構想を変更しました。

理由としては、今後テーブルを増やすことでService内の関数が肥大しないようにするため、
他のViewModelでの使い回しが効くようにしたかったためです。

以下、実装したコードです。

App.xaml.cs

C#

1namespace TempWpfApp 2{ 3 /// <summary> 4 /// Interaction logic for App.xaml 5 /// </summary> 6 public partial class App 7 { 8 protected override Window CreateShell() => Container.Resolve<MainWindow>(); 9 10 protected override void RegisterTypes(IContainerRegistry container) 11 { 12 container.RegisterForNavigation<HomeView>(); 13 14 containerRegistry.Register<ITransactionContext, TransactionContext>(); 15 containerRegistry.Register<IUserService , UserService>(); 16 } 17 18 protected override void OnInitialized() 19 { 20 base.OnInitialized(); 21 22 Container.Resolve<IRegionManager>().RequestNavigate("MainRegion", nameof(HomeView)); 23 24 } 25 } 26}

HomeViewModel

C#

1namespace TempWpfApp.ViewModels 2{ 3 class HomeViewModel 4 { 5 private IUserService userService; 6 7 public HomeViewModel(IUserService userService) 8 { 9 _userService= userService; 10 11 // 例 12 this.Iput.Value = _userService.Name; 13 } 14 15 public ReactivePropertySlim<string> Input { get; } = new ReactivePropertySlim<string>(); 16 17 } 18}

NavigationService.cs

C#

1namespace TempWpfApp.Service 2{ 3 class UserService : IUserService 4 { 5 private ITransactionContext _transactionContext; 6 7 public UserService(ITransactionContext transactionContext) 8 { 9 _transactionContext = transactionContext; 10 } 11 12 public User GetUser() 13 => _transactionContext.DataContext.User.First(); 14 15 } 16}

IUserService.cs

C#

1namespace TempWpfApp.ServiceInterface 2{ 3 public interface IUserService 4 { 5 User GetUser(); 6 } 7}

TransactionContext.cs

C#

1namespace TempWpfApp.Database 2{ 3 class TransactionContext : ITransactionContext 4 { 5 public DataContext DataContext { get; } 6 7 public TransactionContext() 8 { 9 DataContext = new DataContext(); 10 } 11 } 12}

ITransactionContext.cs

C#

1namespace TempWpfApp.Database 2{ 3 public interface ITransactionContext 4 { 5 DataContext DataContext { get; } 6 } 7}

アドバイス頂いた、hihijiji様とSurferOnWww様
ありがとうございます。

投稿2020/08/26 11:32

neko_usagi

総合スコア10

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.36%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問