Habréã§ã¯ããã¡ã€ã³ããªãã³ãã¶ã€ã³ã«é¢ããèšäºã ãã§ãªããäžè¬çãªã¢ãŒããã¯ãã£ãš.Netã®äŸã®äž¡æ¹ãå·çãããŠããŸãã ãããåæã«ãValue Objectsã®ãããªãã®ã¢ãŒããã¯ãã£ã®éèŠãªéšåã«ã€ããŠã¯ãã»ãšãã©èšåãããŠããŸããã
ãã®èšäºã§ã¯ãEntity Framework Coreã䜿çšããŠ.Net Coreã«Valueãªããžã§ã¯ããå®è£
ããããšã®åŸ®åŠãªéããæããã«ããŸãã
ç«ã®äžã«ã¯ããããã®ã³ãŒãããããŸãã
çè«ã®ããã
ãã¡ã€ã³é§åèšèšã®ã¢ãŒããã¯ãã£ã®äžæ žã¯ãã¡ã€ã³ã§ããããã¯ãéçºäžã®ãœãããŠã§ã¢ãé©çšããããµããžã§ã¯ãé åã§ãã éåžžãããŸããŸãªããŒã¿ãšããåãããã¢ããªã±ãŒã·ã§ã³ã®ããžãã¹ããžãã¯å
šäœã瀺ããŸãã ããŒã¿ã«ã¯æ¬¡ã®2ã€ã®ã¿ã€ãããããŸãã
- ãšã³ãã£ãã£ãªããžã§ã¯ã
- å€ãªããžã§ã¯ãïŒä»¥é-VOïŒ
ãšã³ãã£ãã£ãªããžã§ã¯ãã¯ãããžãã¹ããžãã¯ã§ãšã³ãã£ãã£ãå®çŸ©ããåžžã«ãšã³ãã£ãã£ãèŠã€ãããå¥ã®ãšã³ãã£ãã£ãšæ¯èŒãããããããã®èå¥åãæã£ãŠããŸãã 2ã€ã®ãšã³ãã£ãã£ã®èå¥åãåãå Žåãããã¯åããšã³ãã£ãã£ã§ãã ã»ãšãã©åžžã«å€åããŸãã
å€ãªããžã§ã¯ãã¯äžå€ã®ã¿ã€ãã§ããããã®å€ã¯äœæäžã«èšå®ããããªããžã§ã¯ãã®åç¶æéãéããŠå€åããŸããã èå¥åã¯ãããŸããã 2ã€ã®VOãæ§é çã«åäžã§ããå Žåããããã¯åçã§ãã
ãšã³ãã£ãã£ã«ã¯ãä»ã®ãšã³ãã£ãã£ãšVOãå«ãŸããå ŽåããããŸãã VOã«ã¯ä»ã®VOãå«ããããšãã§ããŸããããšã³ãã£ãã£ã¯å«ããããšãã§ããŸããã
ãããã£ãŠããã¡ã€ã³ããžãã¯ã¯Entityããã³VOã§ã®ã¿åäœããã¯ãã§ã-ããã«ããããã®äžè²«æ§ãä¿èšŒãããŸãã æååãæŽæ°ãªã©ã®åºæ¬çãªããŒã¿åã å€ãã®å Žåããã¡ã€ã³ã®ç¶æ
ã«éåããã ãã§ãããããVOãšããŠæ©èœããããšã¯ã§ããŸãããããã¯ãDDDã®ãã¬ãŒã ã¯ãŒã¯ã§ã¯ã»ãšãã©çœå®³ã§ãã
äŸã ããŸããŸãªããã¥ã¢ã«ã§ãã¹ãŠã®äººã«ããããããŠããPersonã¯ã©ã¹ã¯ããã°ãã°æ¬¡ã®ããã«è¡šç€ºãããŸãã
public class Person { public int Id { get; set; } public string Name { get; set; } public int Age { get; set; } }
ã·ã³ãã«ã§æç¢º-èå¥åãååã幎霢ãã©ãã§ééããç¯ãããšãã§ããŸããïŒ
ããã«ã¯ããã€ãã®ãšã©ãŒããããŸããããšãã°ãããžãã¹ããžãã¯ã®èгç¹ãããååã¯å¿
é ã§ããé·ã0ãŸãã¯100æåãè¶
ããããšã¯ã§ãããç¹æ®æåãå¥èªç¹ãªã©ãå«ããããšã¯ã§ããŸããã ãŸãã幎霢ã¯10æ³æªæºãŸãã¯120æ³ãè¶
ããããšã¯ã§ããŸããã
ããã°ã©ãã³ã°èšèªã®èгç¹ããèŠããšã5ã¯å®å
šã«éåžžã®æŽæ°ã§ãåæ§ã«ç©ºã®æååã§ãã ãããããã¡ã€ã³ã¯ãã§ã«æ£ãããªãç¶æ
ã§ãã
ç·Žç¿ã«ç§»ããŸããã
ãã®æç¹ã§ãVOã¯äžå€ã§ãããããžãã¹ããžãã¯ã«æå¹ãªå€ãå«ãå¿
èŠãããããšãããããŸãã
èæ§ã¯ããªããžã§ã¯ãã®äœææã«èªã¿åãå°çšããããã£ãåæåããããšã«ããå®çŸãããŸãã
å€ã®æ€èšŒã¯ãã³ã³ã¹ãã©ã¯ã¿ãŒã§çºçããŸãïŒGuardå¥ïŒã ä»ã®ã¬ã€ã€ãŒãã¯ã©ã€ã¢ã³ãïŒåããã©ãŠã¶ãŒïŒããåä¿¡ããããŒã¿ãæ€èšŒã§ããããã«ãæ€èšŒèªäœãå
¬éããããšãæãŸããã§ãã
ååãšå¹Žéœ¢ã®VOãäœæããŸãããã ããã«ãã¿ã¹ã¯ãå°ãè€éã«ããŸã-FirstNameãšLastNameãçµã¿åãããPersonalNameã远å ãããããPersonã«é©çšããŸãã
ãåå public class Name { private static readonly Regex ValidationRegex = new Regex( @"^[\p{L}\p{M}\p{N}]{1,100}\z", RegexOptions.Singleline | RegexOptions.Compiled); public Name(String value) { if (!IsValid(value)) { throw new ArgumentException("Name is not valid"); } Value = value; } public String Value { get; } public static Boolean IsValid(String value) { return !String.IsNullOrWhiteSpace(value) && ValidationRegex.IsMatch(value); } public override Boolean Equals(Object obj) { return obj is Name other && StringComparer.Ordinal.Equals(Value, other.Value); } public override Int32 GetHashCode() { return StringComparer.Ordinal.GetHashCode(Value); } }
å人å public class PersonalName { protected PersonalName() { } public PersonalName(Name firstName, Name lastName) { if (firstName == null) { throw new ArgumentNullException(nameof(firstName)); } if (lastName == null) { throw new ArgumentNullException(nameof(lastName)); } FirstName = firstName; LastName = lastName; } public Name FirstName { get; } public Name LastName { get; } public String FullName => $"{FirstName} {LastName}"; public override Boolean Equals(Object obj) { return obj is PersonalName personalName && EqualityComparer<Name>.Default.Equals(FirstName, personalName.FirstName) && EqualityComparer<Name>.Default.Equals(LastName, personalName.LastName); } public override Int32 GetHashCode() { return HashCode.Combine(FirstName, LastName); } public override String ToString() { return FullName; } }
幎霢 public class Age { public Age(Int32 value) { if (!IsValid(value)) { throw new ArgumentException("Age is not valid"); } Value = value; } public Int32 Value { get; } public static Boolean IsValid(Int32 value) { return 10 <= value && value <= 120; } public override Boolean Equals(Object obj) { return obj is Age other && Value == other.Value; } public override Int32 GetHashCode() { return Value.GetHashCode(); } }
ãããŠæåŸã«äººïŒ
public class Person { public Person(PersonalName personalName, Age age) { if (personalName == null) { throw new ArgumentNullException(nameof(personalName)); } if (age == null) { throw new ArgumentNullException(nameof(age)); } Id = Guid.NewGuid(); PersonalName= personalName; Age = age; } public Guid Id { get; private set; } public PersonalName PersonalName{ get; set; } public Age Age { get; set; } }
ãããã£ãŠããã«ããŒã ãŸãã¯å¹Žéœ¢ãªãã§Personãäœæããããšã¯ã§ããŸããã ãŸãããééã£ããååããééã£ãã幎霢ãäœæããããšã¯ã§ããŸããã åªããããã°ã©ããŒã¯ãName.IsValidïŒâ JohnâïŒããã³Age.IsValidïŒ35ïŒã¡ãœããã䜿çšããŠãã³ã³ãããŒã©ãŒã§åä¿¡ããããŒã¿ã確å®ã«ãã§ãã¯ããããŒã¿ãæ£ãããªãå Žåãã¯ã©ã€ã¢ã³ãã«éç¥ããŸãã
ãšã³ãã£ãã£ãšVOã®ã¿ã䜿çšããããã«ã¢ãã«å
ã®ãã¹ãŠã®å Žæã§ã«ãŒã«ãäœæãããšã倿°ã®ãšã©ãŒãã身ãå®ãããšãã§ããŸãã誀ã£ãããŒã¿ã¯åçŽã«ã¢ãã«ã«å
¥ããŸããã
æç¶æ§
次ã«ãããŒã¿ãŠã§ã¢ããŠã¹ã«ããŒã¿ãä¿åããèŠæ±ã«å¿ããŠååŸããå¿
èŠããããŸãã Entity Framework CoreãORMãããŒã¿ãŠã§ã¢ããŠã¹-MS SQL ServerãšããŠäœ¿çšããŸãã
DDDã®æç¢ºãªå®çŸ©ïŒæ°žç¶æ§ã¯ãããŒã¿ã¢ã¯ã»ã¹ã®ç¹å®ã®å®è£
ãé ããããã€ã³ãã©ã¹ãã©ã¯ãã£ã¬ã€ã€ãŒã®ãµãã»ããã§ãã
ãã¡ã€ã³ã¯æ°žç¶æ§ã«ã€ããŠäœãç¥ãå¿
èŠããªããããã¯ãªããžããªã®ã€ã³ã¿ãŒãã§ãŒã¹ã®ã¿ã決å®ããŸãã
ãŸããæ°žç¶æ§ã«ã¯ãç¹å®ã®å®è£
ããããã³ã°æ§æãUnitOfWorkãªããžã§ã¯ããå«ãŸããŸãã
ãªããžããªãšäœæ¥åäœãäœæãã䟡å€ããããã©ããã«ã€ããŠã¯ã2ã€ã®æèŠããããŸãã
äžæ¹ã§ããããããã¯å¿
èŠãããŸããããªããªããEntity Framework Coreã§ã¯ããã¯ãã¹ãŠæ¢ã«å®è£
ãããŠããããã§ãã ããŒã¿ã¹ãã¬ãŒãžã«åºã¥ãDAL->ããžãã¹ããžãã¯->ãã¬ãŒã³ããŒã·ã§ã³ãšãã圢åŒã®ãã«ãã¬ãã«ã¢ãŒããã¯ãã£ãããå ŽåãEF Coreã®æ©èœãçŽæ¥äœ¿çšããªãã§ãã ããã
ãã ããDDDã®ãã¡ã€ã³ã¯ãããŒã¿ã¹ãã¬ãŒãžãšäœ¿çšãããORMã«äŸåããŸããããããã¯ãã¹ãŠãæ°žç¶æ§ã«ã«ãã»ã«åãããå®è£
ã®åŸ®åŠãªãã®ã§ãããä»ã®äººã«ã¯é¢ä¿ãããŸããã DbContextãä»ã®ã¬ã€ã€ãŒã«æäŸããå Žåãå®è£
ã®è©³çްãããã«å
¬éããéžæããORMã«ç·å¯ã«ãã€ã³ããããã¹ãŠã®ããžãã¹ããžãã¯ã®åºç€ãšããŠDALãååŸããŸãããããã§ã¯ãããŸããã 倧ãŸãã«èšãã°ããã¡ã€ã³ã¯ORMã®å€æŽããã¬ã€ã€ãŒãšããŠã®æ°žç¶æ§ã®åªå€±ã«ããæ°ä»ããªãã¯ãã§ãã
ãã¡ã€ã³å
ã®Personsãªããžããªã€ã³ã¿ãŒãã§ãŒã¹ïŒ
public interface IPersons { Task Add(Person person); Task<IReadOnlyList<Person>> GetList(); }
ããã³æ°žç¶æ§ã§ã®å®è£
ïŒ
public class EfPersons : IPersons { private readonly PersonsDemoContext _context; public EfPersons(UnitOfWork unitOfWork) { if (unitOfWork == null) { throw new ArgumentNullException(nameof(unitOfWork)); } _context = unitOfWork.Context; } public async Task Add(Person person) { if (person == null) { throw new ArgumentNullException(nameof(person)); } await _context.Persons.AddAsync(person); } public async Task<IReadOnlyList<Person>> GetList() { return await _context.Persons.ToListAsync(); } }
è€éãªããšã¯ãªãããã«èŠããŸãããåé¡ããããŸãã ããã«äœ¿ããEntity Framework Coreã¯ãåºæ¬åïŒstringãintãDateTimeãªã©ïŒã§ã®ã¿æ©èœããPersonalNameãšAgeã«ã€ããŠã¯äœãç¥ããŸããã EF Coreã«ããªã¥ãŒãªããžã§ã¯ããçè§£ããããã«æããŸãããã
æ§æ
Fluent APIã¯ãDDDã§ãšã³ãã£ãã£ãæ§æããã®ã«æé©ã§ãã ãã¡ã€ã³ã¯ãããã³ã°ã®ãã¥ã¢ã³ã¹ã«ã€ããŠäœãç¥ãå¿
èŠããªãããã屿§ã¯é©åã§ã¯ãããŸããã
åºæ¬æ§æPersonConfigurationã䜿çšããŠãPersistenceã«ã¯ã©ã¹ãäœæããŸãã
internal class PersonConfiguration : IEntityTypeConfiguration<Person> { public void Configure(EntityTypeBuilder<Person> builder) { builder.ToTable("Persons"); builder.HasKey(p => p.Id); builder.Property(p => p.Id).ValueGeneratedNever(); } }
DbContextã«ãã©ã°ã€ã³ããŸãã
protected override void OnModelCreating(ModelBuilder builder) { base.OnModelCreating(builder); builder.ApplyConfiguration(new PersonConfiguration()); }
ãããã³ã°
ãã®è³æãäœæãããã»ã¯ã·ã§ã³ã
çŸæç¹ã§ã¯ãéæšæºã¯ã©ã¹ãåºæ¬åã«ãããããããã®2ã€ã®å€ããå°ãªãã䟿å©ãªæ¹æ³ãå€å€æãšææåããããŸãã
å€ã®å€æ
ãã®æ©èœã¯Entity Framework Core 2.1ã«ç»å Žãã2ã€ã®ããŒã¿åéã®å€æã決å®ã§ããŸãã
Ageã®ã³ã³ããŒã¿ãŒãäœæããŸãããïŒãã®ã»ã¯ã·ã§ã³ã§ã¯ããã¹ãŠã®ã³ãŒãã¯PersonConfigurationã«ãããŸãïŒã
var ageConverter = new ValueConverter<Age, Int32>( v => v.Value, v => new Age(v)); builder .Property(p => p.Age) .HasConversion(ageConverter) .HasColumnName("Age") .HasColumnType("int") .IsRequired();
ã·ã³ãã«ã§ç°¡æœãªæ§æã§ãããæ¬ é¥ããªãããã§ã¯ãããŸããïŒ
- nullã倿ã§ããŸããã
- 1ã€ã®ããããã£ãããŒãã«å
ã®è€æ°ã®åã«å€æãããããã®éãè¡ãããšã¯ã§ããŸããã
- EF Coreã¯ããã®ããããã£ãæã€LINQåŒãSQLã¯ãšãªã«å€æã§ããŸããã
æåŸã®ãã€ã³ãã«ã€ããŠè©³ãã説æããŸãã ç¹å®ã®å¹Žéœ¢ã®Personã®ãªã¹ããè¿ãã¡ãœããããªããžããªã«è¿œå ããŸãã
public async Task<IReadOnlyList<Person>> GetOlderThan(Age age) { if (age == null) { throw new ArgumentNullException(nameof(age)); } return await _context.Persons .Where(p => p.Age.Value > age.Value) .ToListAsync(); }
幎霢ã«ã¯æ¡ä»¶ããããŸãããEF Coreã¯ãããSQLã¯ãšãªã«å€æã§ãããWhereïŒïŒã«å°éãããšãããŒãã«å
šäœãã¢ããªã±ãŒã·ã§ã³ã¡ã¢ãªã«ããŒããããã®åŸãLINQã䜿çšããŠãæ¡ä»¶p.Age.Value> age.ValueãæºãããŸãã ã
äžè¬ã«ãValue Conversionsã¯ã·ã³ãã«ã§è¿
éãªãããã³ã°ãªãã·ã§ã³ã§ãããEF Coreã®ãã®æ©èœã«çæããå¿
èŠããããŸããããããªããšãããæç¹ã§å€§ããªããŒãã«ãã¯ãšãªãããšãã«ã¡ã¢ãªãäžè¶³ããå¯èœæ§ããããŸãã
ææã¿ã€ã
ææãããåã¯Entity Framework Core 2.0ã«ç»å Žããéåžžã®Entity Frameworkã®è€éãªåã眮ãæããŸããã
ææã¿ã€ããšããŠå¹Žéœ¢ãäœæããŸãããïŒ
builder.OwnsOne(p => p.Age, a => { a.Property(u => u.Value).HasColumnName("Age"); a.Property(u => u.Value).HasColumnType("int"); a.Property(u => u.Value).IsRequired(); });
æªããªãã ãŸããææã¿ã€ãã«ã¯ãå€å€æã®ãã¡ãªãããã€ãŸããã€ã³ã2ãš3ããããŸããã
2. 1ã€ã®ããããã£ãããŒãã«å
ã®è€æ°ã®åã«ããŸãã¯ãã®é
ã«å€æãã
ããšãã§ããŸãã
PersonalNameã«å¿
èŠãªãã®ã§ãããæ§æã¯ãã§ã«å°ããªãŒããŒããŒããããŠããŸãã
builder.OwnsOne(b => b.PersonalName, pn => { pn.OwnsOne(p => p.FirstName, fn => { fn.Property(x => x.Value).HasColumnName("FirstName"); fn.Property(x => x.Value).HasColumnType("nvarchar(100)"); fn.Property(x => x.Value).IsRequired(); }); pn.OwnsOne(p => p.LastName, ln => { ln.Property(x => x.Value).HasColumnName("LastName"); ln.Property(x => x.Value).HasColumnType("nvarchar(100)"); ln.Property(x => x.Value).IsRequired(); }); });
3. EF Core
㯠ããã®ããããã£ãæã€LINQåŒãSQLã¯ãšãªã«å€æ
ã§ããŸãã
ãªã¹ããèªã¿èŸŒããšãã«ãLastNameãšFirstNameã«ããäžŠã¹æ¿ãã远å ããŸãã
public async Task<IReadOnlyList<Person>> GetList() { return await _context.Persons .OrderBy(p => p.PersonalName.LastName.Value) .ThenBy(p => p.PersonalName.FirstName.Value) .ToListAsync(); }
ãã®ãããªåŒã¯SQLã¯ãšãªã«æ£ãã倿ãããäžŠã¹æ¿ãã¯ã¢ããªã±ãŒã·ã§ã³ã§ã¯ãªãSQLãµãŒããŒåŽã§å®è¡ãããŸãã
ãã¡ãããæ¬ ç¹ããããŸãã
- nullã®åé¡ã¯è§£æ¶ãããŠããŸããã
- ææã¿ã€ãã®ãã£ãŒã«ãã¯èªã¿åãå°çšã«ã¯ã§ãããä¿è·ãããã»ãã¿ãŒãŸãã¯ãã©ã€ããŒãã»ãã¿ãŒãå¿
èŠã§ãã
- ææã¿ã€ãã¯éåžžã®ãšã³ãã£ãã£ãšããŠå®è£
ãããŸããã€ãŸããæ¬¡ã®ããšãæå³ããŸãã
- ãããã«ã¯èå¥åããããŸãïŒã·ã£ããŠããããã£ã®ããã«ãã€ãŸããã¡ã€ã³ã¯ã©ã¹ã«è¡šç€ºãããŸããïŒã
- EF Coreã¯ãéåžžã®ãšã³ãã£ãã£ãšãŸã£ããåãããã«ãææã¿ã€ãã®ãã¹ãŠã®å€æŽã远跡ããŸãã
äžæ¹ã§ãããã¯ãå€ãªããžã§ã¯ãã®ããã¹ãå§¿ã§ã¯ãããŸããã èå¥åãå«ããããšã¯ã§ããŸããã VOã¯å€æŽã远跡ãã¹ãã§ã¯ãããŸãã-æåã¯äžå€ãªã®ã§ã芪Entityã®ããããã£ã¯è¿œè·¡ãã¹ãã§ãããVOã®ããããã£ã¯è¿œè·¡ãã¹ãã§ã¯ãããŸããã
äžæ¹ããããã¯å®è£
ã®è©³çްã§ãããçç¥ã§ããŸãããå¿ããªãã§ãã ããã 倿Žã®è¿œè·¡ã¯ããã©ãŒãã³ã¹ã«åœ±é¿ããŸãã åäžã®ãšã³ãã£ãã£ã®ãµã³ãã«ïŒããšãã°ãIdã«ããïŒãŸãã¯å°ããªãªã¹ãã§ãããç®ç«ããªãå Žåããéãããšã³ãã£ãã£ïŒå€ãã®VOããããã£ïŒã®å€§ããªãªã¹ãã®éžæã§ã¯ã远跡ã®ããã«ããã©ãŒãã³ã¹ã®äœäžãéåžžã«é¡èã«ãªããŸãã
ãã¬ãŒã³ããŒã·ã§ã³
ãã¡ã€ã³ãšãªããžããªã«å€ãªããžã§ã¯ããå®è£
ããæ¹æ³ãèŠã€ããŸããã ããããã¹ãŠäœ¿çšããæãæ¥ãŸããã ãªã¹ãPersonãšPersonã远å ããããã®ãã©ãŒã ã®2ã€ã®ã·ã³ãã«ãªããŒãžãäœæããŸãããã
ã¢ã¯ã·ã§ã³ã¡ãœããã®ãªãã³ã³ãããŒã©ãŒã³ãŒãã¯æ¬¡ã®ããã«ãªããŸãã
public class HomeController : Controller { private readonly IPersons _persons; private readonly UnitOfWork _unitOfWork; public HomeController(IPersons persons, UnitOfWork unitOfWork) { if (persons == null) { throw new ArgumentNullException(nameof(persons)); } if (unitOfWork == null) { throw new ArgumentNullException(nameof(unitOfWork)); } _persons = persons; _unitOfWork = unitOfWork; }
ã¢ã¯ã·ã§ã³ã远å ããŠãå人ãªã¹ããååŸããŸãã
[HttpGet] public async Task<IActionResult> Index() { var persons = await _persons.GetList(); var result = new PersonsListModel { Persons = persons .Select(CreateModel) .ToArray() }; return View(result); }
衚瀺ãã @model PersonsListModel @{ ViewData["Title"] = "Persons List"; } <div class="text-center"> <h2 class="display-4">Persons</h2> </div> <table class="table"> <thead> <tr> <td><b>Last name</b></td> <td><b>First name</b></td> <td><b>Age</b></td> </tr> </thead> @foreach (var p in Model.Persons) { <tr> <td>@p.LastName</td> <td>@p.FirstName</td> <td>@p.Age</td> </tr> } </table>
è€éãªããšã¯ãããŸãã-ãªã¹ããããŠã³ããŒãããããããã«ããŒã¿è»¢éãªããžã§ã¯ãïŒPersonModelïŒãäœæããŸãã
å人ããã³å¯Ÿå¿ãããã¥ãŒã«éä¿¡ãããŸãã
ããã«è峿·±ãã®ã¯ãPersonã®è¿œå ã§ãã
[HttpPost] public async Task<IActionResult> AddPerson(PersonModel model) { if (model == null) { return BadRequest(); } if (!Name.IsValid(model.FirstName)) { ModelState.AddModelError(nameof(model.FirstName), "FirstName is invalid"); } if (!Name.IsValid(model.LastName)) { ModelState.AddModelError(nameof(model.LastName), "LastName is invalid"); } if (!Age.IsValid(model.Age)) { ModelState.AddModelError(nameof(model.Age), "Age is invalid"); } if (!ModelState.IsValid) { return View(); } var firstName = new Name(model.FirstName); var lastName = new Name(model.LastName); var person = new Person( new PersonalName(firstName, lastName), new Age(model.Age)); await _persons.Add(person); await _unitOfWork.Commit(); var persons = await _persons.GetList(); var result = new PersonsListModel { Persons = persons .Select(CreateModel) .ToArray() }; return View("Index", result); }
衚瀺ãã @model PersonDemo.Models.PersonModel @{ ViewData["Title"] = "Add Person"; } <h2 class="display-4">Add Person</h2> <div class="row"> <div class="col-md-4"> <form asp-action="AddPerson"> <div asp-validation-summary="ModelOnly" class="text-danger"></div> <div class="form-group"> <label asp-for="FirstName" class="control-label"></label> <input asp-for="FirstName" class="form-control" /> <span asp-validation-for="FirstName" class="text-danger"></span> </div> <div class="form-group"> <label asp-for="LastName" class="control-label"></label> <input asp-for="LastName" class="form-control" /> <span asp-validation-for="LastName" class="text-danger"></span> </div> <div class="form-group"> <label asp-for="Age" class="control-label"></label> <input asp-for="Age" class="form-control" /> <span asp-validation-for="Age" class="text-danger"></span> </div> <div class="form-group"> <input type="submit" value="Create" class="btn btn-primary" /> </div> </form> </div> </div> @section Scripts { @{await Html.RenderPartialAsync("_ValidationScriptsPartial");} }
åä¿¡ããŒã¿ã®å¿
é ã®æ€èšŒããããŸãïŒ
if (!Name.IsValid(model.FirstName)) { ModelState.AddModelError(nameof(model.FirstName), "FirstName is invalid"); }
ãããè¡ãããªãå Žåãééã£ãå€ã§VOãäœæãããšãArgumentExceptionãã¹ããŒãããŸãïŒVOã³ã³ã¹ãã©ã¯ã¿ãŒã®Guard ClauseãæãåºããŠãã ããïŒã æ€èšŒã䜿çšãããšãå€ã®1ã€ãééã£ãŠãããšããã¡ãã»ãŒãžããŠãŒã¶ãŒã«éä¿¡ããã®ãã¯ããã«ç°¡åã«ãªããŸãã
ããã§ã¯ãAsp Net Coreã§å±æ§ã䜿çšããŠãããŒã¿æ€èšŒã®éåžžã®æ¹æ³ãããå°ããªäœè«ãããå¿
èŠããããŸãã ããããDDDã§ã¯ããã®æ€èšŒæ¹æ³ã¯ããã€ãã®çç±ã§æ£ãããããŸããã
- 屿§æ©èœã¯ãæ€èšŒããžãã¯ã«ã¯äžååãªå ŽåããããŸãã
- ãã©ã¡ãŒã¿ãŒæ€èšŒã®ã«ãŒã«ãå«ãããžãã¹ããžãã¯ã¯ããã¡ã€ã³ã«ãã£ãŠæä»çã«èšå®ãããŸãã 圌ã¯ãããç¬å ããŠãããä»ã®ãã¹ãŠã®å±€ã¯ãããèæ
®ããªããã°ãªããŸããã 屿§ã䜿çšã§ããŸããããããã«äŸåããªãã§ãã ããã 屿§ã誀ã£ãããŒã¿ãã¹ãããããå ŽåãVOã®äœææã«åã³äŸå€ãçºçããŸãã
AddPersonïŒïŒã«æ»ããŸãã ããŒã¿æ€èšŒã®åŸãPersonalNameãAgeãPersonãäœæãããŸãã æ¬¡ã«ããªããžããªã«ãªããžã§ã¯ãã远å ãã倿Žãä¿åããŸãïŒã³ãããïŒã EfPersonsãªããžããªã§CommitãåŒã³åºãããªãããšãéåžžã«éèŠã§ãã ãªããžããªã®ã¿ã¹ã¯ã¯ãããŒã¿ã«å¯ŸããŠäœããã®ã¢ã¯ã·ã§ã³ãå®è¡ããããšã§ãã ã³ãããã¯ãå³å¯ã«èšãã°å€éšã§ã®ã¿è¡ãããŸã-ããã°ã©ããŒã決å®ããŸãã ããããªããšãç¹å®ã®ããžãã¹ã®å埩ã®éäžã§ãšã©ãŒãçºçãããšãã«ç¶æ³ãçºçããå¯èœæ§ããããŸããäžéšã®ããŒã¿ã¯ä¿åãããäžéšã¯ä¿åãããŸããã ãå£ãããç¶æ
ã®ãã¡ã€ã³ãåãåããŸãã ã³ããããæåŸã«è¡ããããšã©ãŒãçºçããå Žåããã©ã³ã¶ã¯ã·ã§ã³ã¯åã«ããŒã«ããã¯ãããŸãã
ãããã«
ããªã¥ãŒãã¬ãŒã ã¯ãŒã¯ã®äžè¬çãªå®è£
äŸãšãEntity Framework Coreã§ã®ãããã³ã°ã®ãã¥ã¢ã³ã¹ã瀺ããŸããã ãã®è³æãããã¡ã€ã³é§åèšèšã®èŠçŽ ãå®éã«é©çšããæ¹æ³ãçè§£ããã®ã«åœ¹ç«ã€ããšãé¡ã£ãŠããŸãã
å®å
šãªPersonsDemoãããžã§ã¯ãã®ãœãŒã¹ã³ãŒã-GitHub
ãã®è³æã¯ãPersonalNameãŸãã¯AgeãPersonã®å¿
é ããããã£ã§ã¯ãªãå Žåããªãã·ã§ã³ã®ïŒnullå¯èœïŒå€ãªããžã§ã¯ããšå¯Ÿè©±ããåé¡ãé瀺ããŠããŸããã ãã®èšäºã§ããã説æãããã£ãã®ã§ããããã§ã«å€å°ã®éè² è·ãçããŠããŸãã ãã®åé¡ã«é¢å¿ãããå Žå-ã³ã¡ã³ããæžããŠãã ãããç¶ç¶ã¯ãããªããŸãã
äžè¬ã«ãçŸããã¢ãŒããã¯ãã£ããç¹ã«ãã¡ã€ã³é§ååãã¶ã€ã³ã®ãã¡ã³ã«ã¯ã
Enterprise CraftsmanshipãªãœãŒã¹ã匷ããå§ãããŸãã
.Netã«ã¯ãã¢ãŒããã¯ãã£ã®é©åãªæ§ç¯ãšå®è£
äŸã«é¢ããå€ãã®æçšãªèšäºããããŸãã ããã§ããã€ãã®ã¢ã€ãã¢ãåãå
¥ãããããæŠéããããžã§ã¯ãã«ããŸãå®è£
ããããã®èšäºã«éšåçã«åæ ãããŸããã
ææã¿ã€ããš
å€ã®å€æã®å
¬åŒããã¥ã¡ã³ãã䜿çšãããŸããã