Created
October 21, 2017 14:32
-
-
Save ichiroku11/750445e18a0d4259549e060fd7cf21d5 to your computer and use it in GitHub Desktop.
EF CoreのOwned typesのサンプル
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
use Test; | |
begin tran; | |
-- テーブル作成 | |
drop table if exists dbo.Character; | |
create table dbo.Character( | |
Id int, | |
Name nvarchar(4) not null, | |
Level int not null, | |
Hp int not null, | |
Mp int not null, | |
constraint PK_Character primary key(Id) | |
); | |
/* | |
-- データ投入 | |
insert into dbo.Character( | |
Id, Name, Level, Hp, Mp | |
) | |
output inserted.* | |
values | |
(1, N'エイト', 10, 59, 32), | |
(2, N'ゼシカ', 10, 47, 28); | |
*/ | |
commit; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Collections.Generic; | |
using System.Data.SqlClient; | |
using System.Linq; | |
using Microsoft.EntityFrameworkCore; | |
using Microsoft.EntityFrameworkCore.Infrastructure; | |
using Microsoft.Extensions.DependencyInjection; | |
using Microsoft.Extensions.Logging; | |
using Microsoft.Extensions.Logging.Abstractions; | |
namespace ConsoleApp { | |
// ステータス | |
public class Status { | |
// HP | |
public int Hp { get; set; } | |
// MP | |
public int Mp { get; set; } | |
} | |
/* | |
public class Status { | |
// 最大HP | |
public int MaxHp { get; set; } | |
// 最大MP | |
public int MaxMp { get; set; } | |
// ちから | |
public int Strength { get; set; } | |
// すばやさ | |
public int Speed { get; set; } | |
// みのまもり | |
public int Guard { get; set; } | |
// かしこさ | |
public int Wisdom { get; set; } | |
// 攻撃力 | |
public int Attack { get; set; } | |
// 守備力 | |
public int Defense { get; set; } | |
} | |
*/ | |
// キャラクター | |
public class Character { | |
public int Id { get; set; } | |
public string Name { get; set; } | |
public int Level { get; set; } | |
public Status Status { get; set; } | |
} | |
// ロガープロバイダー | |
public class AppLoggerProvider : ILoggerProvider { | |
public ILogger CreateLogger(string categoryName) { | |
if (string.Equals(categoryName, DbLoggerCategory.Database.Command.Name)) { | |
return new ConsoleLogger(); | |
} | |
return NullLogger.Instance; | |
} | |
public void Dispose() { | |
} | |
// ロガー | |
private class ConsoleLogger : ILogger { | |
public IDisposable BeginScope<TState>(TState state) => null; | |
// 情報レベル以上のログを有効にする | |
public bool IsEnabled(LogLevel logLevel) => logLevel >= LogLevel.Information; | |
public void Log<TState>(LogLevel logLevel, EventId eventId, TState state, Exception exception, | |
Func<TState, Exception, string> formatter) { | |
Console.WriteLine(formatter(state, exception)); | |
Console.WriteLine("---"); | |
} | |
} | |
} | |
// DBコンテキスト | |
public class AppDbContext : DbContext { | |
public AppDbContext(bool tracking = false) { | |
ChangeTracker.QueryTrackingBehavior = tracking | |
? QueryTrackingBehavior.TrackAll | |
: QueryTrackingBehavior.NoTracking; | |
} | |
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) { | |
var connectionString = new SqlConnectionStringBuilder { | |
DataSource = ".", | |
InitialCatalog = "Test", | |
IntegratedSecurity = true, | |
}.ToString(); | |
optionsBuilder.UseSqlServer(connectionString); | |
} | |
protected override void OnModelCreating(ModelBuilder modelBuilder) { | |
// Characterテーブルへのマッピング | |
modelBuilder.Entity<Character>().ToTable(nameof(Character)); | |
// CharacterがStatusを所有する | |
modelBuilder.Entity<Character>().OwnsOne( | |
character => character.Status, | |
statusBuilder => { | |
// Statusをカラムへマッピング | |
// デフォルトだと「Status_Hp」「「Status_Mp」」といったカラムにマッピングされる | |
statusBuilder.Property(status => status.Hp).HasColumnName(nameof(Status.Hp)); | |
statusBuilder.Property(status => status.Mp).HasColumnName(nameof(Status.Mp)); | |
}); | |
} | |
} | |
class Program { | |
private static void Dump(IEnumerable<Character> characters) { | |
foreach (var character in characters) { | |
Console.WriteLine($"{character.Name}"); | |
Console.WriteLine($"Lv {character.Level}"); | |
Console.WriteLine($"HP {character.Status.Hp}"); | |
Console.WriteLine($"MP {character.Status.Mp}"); | |
Console.WriteLine(); | |
} | |
} | |
static void Main(string[] args) { | |
using (var dbContext = new AppDbContext()) { | |
// ロガープロバイダーを設定 | |
var serviceProvider = dbContext.GetInfrastructure(); | |
var loggerFactory = serviceProvider.GetService<ILoggerFactory>(); | |
loggerFactory.AddProvider(new AppLoggerProvider()); | |
} | |
// データ投入 | |
using (var dbContext = new AppDbContext(tracking: true)) { | |
dbContext.Set<Character>().AddRange( | |
new Character { | |
Id = 1, | |
Name = "エイト", | |
Level = 10, | |
Status = new Status { Hp = 59, Mp = 32 }, | |
}, | |
new Character { | |
Id = 2, | |
Name = "ゼシカ", | |
Level = 10, | |
Status = new Status { Hp = 47, Mp = 28 }, | |
}); | |
dbContext.SaveChanges(); | |
/* | |
Executed DbCommand(36ms) [Parameters=[@p0='?', @p1='?', @p2='?' (Size = 4000), @p3='?', @p4='?', @p5='?', @p6='?', @p7='?' (Size = 4000), @p8='?', @p9='?'], CommandType='Text', CommandTimeout='30'] | |
SET NOCOUNT ON; | |
INSERT INTO[Character] ([Id], [Level], [Name], [Hp], [Mp]) | |
VALUES(@p0, @p1, @p2, @p3, @p4), | |
(@p5, @p6, @p7, @p8, @p9); | |
--- | |
*/ | |
} | |
// 確認 | |
using (var dbContext = new AppDbContext()) { | |
var characters = dbContext.Set<Character>().ToList(); | |
/* | |
Executed DbCommand (1ms) [Parameters=[], CommandType='Text', CommandTimeout='30'] | |
SELECT [c].[Id], [c].[Level], [c].[Name], [c].[Id], [c].[Hp], [c].[Mp] | |
FROM [Character] AS [c] | |
--- | |
*/ | |
Dump(characters); | |
/* | |
エイト | |
Lv 10 | |
HP 59 | |
MP 32 | |
ゼシカ | |
Lv 10 | |
HP 47 | |
MP 28 | |
*/ | |
} | |
// データ更新 | |
using (var dbContext = new AppDbContext(tracking: true)) { | |
// エイトを取得 | |
var character = dbContext.Set<Character>().Find(1); | |
/* | |
Executed DbCommand(1ms) [Parameters=[@__get_Item_0='?'], CommandType='Text', CommandTimeout='30'] | |
SELECT TOP(1) [e].[Id], [e].[Level], [e].[Name], [e].[Id], [e].[Hp], [e].[Mp] | |
FROM[Character] AS[e] | |
WHERE[e].[Id] = @__get_Item_0 | |
--- | |
*/ | |
// エイトがレベルアップ | |
character.Level += 1; | |
character.Status.Hp += 12; | |
character.Status.Mp += 2; | |
dbContext.SaveChanges(); | |
/* | |
SET NOCOUNT ON; | |
UPDATE [Character] SET [Level] = @p0, [Hp] = @p1, [Mp] = @p2 | |
WHERE [Id] = @p3; | |
SELECT @@ROWCOUNT; | |
--- | |
*/ | |
} | |
// 確認 | |
using (var dbContext = new AppDbContext()) { | |
var characters = dbContext.Set<Character>().ToList(); | |
/* | |
Executed DbCommand(0ms) [Parameters=[], CommandType='Text', CommandTimeout='30'] | |
SELECT[c].[Id], [c].[Level], [c].[Name], [c].[Id], [c].[Hp], [c].[Mp] | |
FROM[Character] AS[c] | |
--- | |
*/ | |
Dump(characters); | |
/* | |
エイト | |
Lv 11 | |
HP 71 | |
MP 34 | |
ゼシカ | |
Lv 10 | |
HP 47 | |
MP 28 | |
*/ | |
} | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment