ææ°ã®ãªãŒãã³ãœãŒã¹Webã¢ããªã±ãŒã·ã§ã³ã§ã¯ãNoSQLãœãªã¥ãŒã·ã§ã³ã®äœ¿çšã¯ãéãªã¬ãŒã·ã§ãã«åäœã®ããã«äººæ°ãåããŠããŸãã ãã®èšäºã§ã¯ãMongoDBã®ã³ã¬ã¯ã·ã§ã³ã«é©çšå¯èœãªCRUDæäœããµããŒãããåçŽãªASP.NET Core Web APIãããŒãããã¯ãã¢ããªã±ãŒã·ã§ã³ã段éçã«å®è£ ããŸãã
ãªãmongodb
DBMSã®éžæã¯ãäž»ã«äœæããã¢ããªã±ãŒã·ã§ã³ã«ãã£ãŠç°ãªããŸãã ã€ãŸã ããŒã¿ããŒã¹ã¯éçºè ã«ãã£ãŠéžæãããã®ã§ã¯ãªãã補åèªäœã«ãã£ãŠéžæãããŸãã ããã¥ã¡ã³ããæäœããã«ã¯ãMongoDBãæé©ã§ãã ãã®ãããªã¢ããªã±ãŒã·ã§ã³ã®å°è±¡çãªäŸã¯ãããã°ããœãŒã·ã£ã«ãããã¯ãŒã¯ã§ãåäœæè ãæçš¿ãäœæããç»åããããªãé³æ¥œãè¿œå ã§ããŸãã ä»ã®ãŠãŒã¶ãŒã¯ããããã®ãšã³ããªã«ã³ã¡ã³ããããããããããããæããªã©ã®ã·ã¹ãã è©äŸ¡ã䜿çšããŠè©äŸ¡ãããã§ããŸãã ãããããã®ããŒã¿ãã©ã®ããã«ä¿åããŸããïŒ ãªã¬ãŒã·ã§ãã«DBMSã«ç²ŸéããŠããå Žåãåæ§ã®ã¹ããŒã ãã©ã®ããã«ãªããæ³åã§ããŸãã
åäžã®ã¬ã³ãŒãã®æ§é ãšããã®è¡šç€ºæ¹æ³ãæ³åããŠã¿ãŸãããã ã¬ã³ãŒããšããã«é¢é£ä»ããããããŒã¿ïŒç»åãé³å£°ããããªãã³ã¡ã³ããè©äŸ¡ããŠãŒã¶ãŒæ å ±ãªã©ïŒãååŸããã«ã¯ã8ã€ã®ããŒãã«æ¥ç¶ã«ã€ããŠç §äŒããå¿ èŠããããŸãã ããã§ãåŠçãããã¬ã³ãŒãã®ã¹ããªãŒã ïŒåçã«ããŒããããæ°åã®ã¯ã©ã€ã¢ã³ãã«è»¢éãããïŒãæ³åãããšããã®ã¿ã¹ã¯ã«ã¯å€æ°ã®ããŒãã«çµåã«å¯Ÿããæ°åã®ã¯ãšãªãå¿ èŠã§ããããšãããããŸãã ãã¡ãããããŒã¿ã¹ãã¬ãŒãžã«ã¯ãSQL Serverãªã©ã®ãªã¬ãŒã·ã§ãã«ããŒã¿ããŒã¹ã䜿çšã§ããŸãã SQLã¯JSON圢åŒã®åçããŒã¿ããµããŒãããŸã ã ãã ãããã®ç¹å®ã®ã·ããªãªã®ã¢ãããŒããç°¡çŽ åãããªãã·ã§ã³ããããŸã-ããã¯NoSQLããŒã¿ããŒã¹ã§ãã 以äžã«ç€ºãããã«1ã€ã®ããã¥ã¡ã³ãã䜿çšããŠMongoDBã«ä¿åãããšãã¢ããªã±ãŒã·ã§ã³ã®ããã©ãŒãã³ã¹ãåäžãããããŒãã«çµåã®ãªãåäžã®ã¯ãšãªã§å®å šã«ã¬ã³ãŒããååŸã§ããŸãã ããã¯ãããã·ã³ãã«ã§å¹ççãªæ¹æ³ã§ãã
{ "id":"ew12-res2-234e-544f", "title":"post title", "date":"2016-01-01", "body":"this is an awesome post stored on NoSQL", "createdBy":"User", "images":["http://example.com/myfirstimage.png","http://example.com/mysecondimage.png"], "videos":[ {"url":"http://example.com/myfirstvideo.mp4", "title":"The first video"}, {"url":"http://example.com/mysecondvideo.mp4", "title":"The second video"} ], "audios":[ {"url":"http://example.com/myfirstaudio.mp3", "title":"The first audio"}, {"url":"http://example.com/mysecondaudio.mp3", "title":"The second audio"} ] }
ããã«ãMongoDBã䜿çšãããšãéçºè ã¯é«å¯çšæ§ãšäœé 延ã®ã¢ããªã±ãŒã·ã§ã³ãäœæããããšã§äžè²«æ§ãç·©ããããšãã§ããŸãã
MongoDBããªã¬ãŒã·ã§ãã«ããŒã¿ããŒã¹ã®ä»£æ¿ãšåŒã¶ããšã¯å®å šã«æ£ããããã§ã¯ãªããããã代æ¿ã§ããããšã«æ³šæããŠãã ããã ãã®ããŒã«ã¯ãä»ã®å€ãã®äººãã§ããããšãšåãããšãè¡ãããšãã§ããŸã-äœããåªããŠããŸãããããã§ã¯ãããŸããã
MongoDBã®éæ§é åã³ã¬ã¯ã·ã§ã³ã¢ãŒããã¯ãã£ã¯ãéçºè ãããŒã¿ã¬ãã«ã®ã¹ããŒããå®çŸ©ããã³ä¿å®ããããšã矩åä»ããŠããªãããã補åéçºäžã«è¿ éãªå埩ãå¯èœã§ãã ãªããžã§ã¯ããä¿åããå¿ èŠããããŸããïŒ BSONã«ã·ãªã¢ã«åããMongoDBã«éä¿¡ããŸãã ããããã£ãŸãã¯ã¿ã€ãã®ãããã³ã°ã¯ãããŸããã
ãã®ã·ã³ãã«ãã¯ã究極ã®éçºè ãšããŠééããªãããªãã«åã£ãŠããã§ãããã
ããŒãžã§ã³1.8ããåã¯ãMongoDBã¯ã¹ãã¬ãŒãžã«é¢ããŠä¿¡é Œæ§ãäœããšèŠãªãããŠããŸãããããã®ããŒãžã§ã³ã§ã¯ãã®ã³ã°ã¡ã«ããºã ãè¿œå ãããããã©ã«ãã§ãã§ã«æå¹ã«ãªã£ãŠããŸãããæ§æãã¡ã€ã«ã§ç¡å¹ã«ã§ããŸãã ããã©ãŒãã³ã¹ã¯ãããã«åäžããŸããããã®ã³ã°ã¡ã«ããºã ãç¡å¹ã«ãªã£ãŠãããšãããŒã¿æ倱ã®ãªã¹ã¯ããããŸãã
æè¡ã¹ã¿ãã¯
MongoDBã¯ãBSONïŒBinary JavaScript Object NotationïŒåœ¢åŒã®ããã¥ã¡ã³ããšããŒã¿ããŒã¹ã¹ããŒãã䜿çšããŸããããã¯ãè¿œå ã®æ£èŠè¡šçŸããã€ããªããŒã¿ãæ¥ä»ãªã©ã®ããŒã¿ãä¿åããããã®JSON圢åŒã®ã¹ãŒããŒã»ããã§ãã MongoDBã®ã¹ããŒãã¯ã³ã¬ã¯ã·ã§ã³ãšåŒã°ãããã®ã¹ããŒãã®ãšã³ããªã¯ããã¥ã¡ã³ããšåŒã°ããŸã ã
ASP.NET Core Web APIã¯ãHTTPãµãŒãã¹ãšããŠäœ¿çšã§ãããã¹ã¯ãããã³ã³ãã¥ãŒã¿ãŒããæºåž¯é»è©±ãŸã§ãããããã¯ã©ã€ã¢ã³ãã¢ããªã±ãŒã·ã§ã³ã§äœ¿çšã§ããWindowsãMacOSãLinuxã«ãã€ã³ã¹ããŒã«ã§ããããã倧ããªå©ç¹ããããŸãã
泚 ïŒçŸåšãMongoDBã¯EF Coreã§ã¯ãµããŒããããŠããŸããã EF Coreã®å°æ¥ã®ããŒãžã§ã³ãïŒRowan Millerã®ã³ã¡ã³ãã«åºã¥ããŠïŒMongoDBããµããŒãããå¯èœæ§ã¯ã»ãšãã©ãããŸãããããã®æ©èœã¯å°æ¥å®è£ ã§ããŸãã
以äžã¯ãæäœã«å¿ èŠãªãã¹ãŠã®ã³ã³ããŒãã³ãã§ãã
- .NET Coreãå«ãVisual Studio Community 2017
- MongoDBããŒãžã§ã³3.4
- Robomongo-ãã€ãã£ã MongoDB管çããŒã«
- Postman -Web APIãã¹ãããŒã«
MongoDBã®æ§æ
MongoDBãã€ã³ã¹ããŒã«ããã ãããŒã¿ããŒã¹ãžã®ã¢ã¯ã»ã¹ãæ§æãããšãšãã«ãããŒã¿ã®å Žæã瀺ãå¿ èŠããããŸãã ãããè¡ãã«ã¯ã mongod.cfgãã¡ã€ã«ãäœæããŸãã ãã®ãã¡ã€ã«ã«ã¯ãMongoDBãµãŒããŒããŒã¿ãã©ã«ããŒãžã®ãã¹ãšMongoDBãã°ãã¡ã€ã«ãå«ãŸããŸããæåã¯èªèšŒãªãã§ãã
systemLog: destination: file path: "C:\\data\\db\\log\\mongo.log" logAppend: true storage: dbPath: "C:\\data\\db"
泚ïŒããã©ã«ãã§ã¯ãMongoDBã¯ã¢ãã¬ã¹
"C:\\data\\db"
ã§ããŒã¿ããŒã¹ãã£ã¬ã¯ããªã®åæåãè©Šã¿ããã®ã¢ãã¬ã¹ãç¹å®ã§ããªãå Žåã¯ãšã©ãŒãã¹ããŒããŸãã
次ã«ãã³ãã³ãã©ã€ã³ã§æ¬¡ã®ã³ãã³ããå®è¡ããŸãïŒæ§æãã¡ã€ã«ã®å ŽæãšMongoDBãã€ã³ã¹ããŒã«ãããŠãããã©ã«ããŒã®å Žæã«å¿ããŠã¢ãã¬ã¹ãæŽæ°ããå¿ èŠããããŸãïŒã
"C:\Program Files\MongoDB\Server\3.4\bin\mongod.exe" --config C:\Dev\mongod.cfg
ãã®ã³ãã³ãã¯ãMongoDBãµãŒããŒãèµ·åããäœææžã¿ã®æ§æãã¡ã€ã«ãæå®ããŸãã
泚ïŒãã€ããªãžã®çµ¶å¯Ÿãã¹ãæå®ããããšã¯ãå§ãã§ããŸããã ãã®ã¢ãã¬ã¹ãéäžçã«äœ¿çšããã«ã¯ãPATHã·ã¹ãã å€æ°ã«ãã£ã¬ã¯ããªãã¹ãè¿œå ããããšããå§ãããŸãã
ãµãŒããŒãèµ·åãããïŒãã°ãã¡ã€ã«ã§è©³çŽ°ã確èªã§ããŸãïŒãã³ãã³ãã©ã€ã³ããmongo.exeã¯ã©ã€ã¢ã³ããå®è¡ããŸãã
泚ïŒã¯ã©ã€ã¢ã³ãã¯ãã¢ã¯ã»ã¹å¶åŸ¡ãèšå®ãããŠããªããšããèŠåãçºè¡ããå ŽåããããŸãïŒããã¯åŸã§ä¿®æ£ããŸãïŒ
ã³ã³ãœãŒã«ã¯ã©ã€ã¢ã³ãã§æ¬¡ã®ã³ãã³ããå®è¡ããŠã管çè ã¢ã«ãŠã³ããäœæããŸãã
use admin db.createUser( { user: "admin", pwd: "abc123!", roles: [ { role: "root", db: "admin" } ] } ); exit;
次ã«ããµãŒããŒãåæ¢ããã»ãã¥ãªãã£ãã©ã¡ãŒã¿ãŒãå«ãmongod.cfgæ§æãã¡ã€ã«ãæŽæ°ããŸãã
systemLog: destination: file path: "C:\\data\\db\\log\\mongo.log" logAppend: true storage: dbPath: "C:\\data\\db" security: authorization: enabled
ããããã¯ã adminãŠãŒã¶ãŒã䜿çšããŠMongoDBã«æ¥ç¶ããŸãã
泚 ïŒéåžžã®æäœã§ã¯ã¹ãŒããŒãŠãŒã¶ãŒã®åœ¹å²ïŒãã®å Žåã¯ç®¡çè ïŒã䜿çšããªãããšããå§ãããŸãããåçŽããç¶æããããã«ãåŒãç¶ã1人ã®ãŠãŒã¶ãŒã®ã¿ã䜿çšããŸãã
ASP.NET Web APIãããžã§ã¯ãã®äœæ
å®æããå®è£ ã¯GitHubããããŠã³ããŒãã§ããŸã ã
Visual Studioããã¡ã€ã«âæ°èŠãããžã§ã¯ãâ.Net CoreâASP.NET Core Webã¢ããªã±ãŒã·ã§ã³ãèµ·åããŸãã
次ã«ãWeb APIãã³ãã¬ãŒããéžæãã[OK]ãã¯ãªãã¯ããŸãã
ãããžã§ã¯ãæ§æ
ãµããŒããããŠããããã€ãã®æ§æãã¡ã€ã«åœ¢åŒïŒJSONãXMLããŸãã¯iniïŒããããããã©ã«ãã§ã¯ãWeb APIãããžã§ã¯ããã³ãã¬ãŒãã¯JSON圢åŒã®æ§æã§ãããã€ãããŸãã AppSettings.jsonãã¡ã€ã«ãæŽæ°ããŠãããŒã¿ããŒã¹æ¥ç¶æ å ±ãè¿œå ããŸãã
{ "Logging": { "IncludeScopes": false, "LogLevel": { "Default": "Debug", "Microsoft": "Information", "System": "Information" } }, "MongoConnection": { "ConnectionString": "mongodb://admin:abc123!@localhost", "Database": "NotesDb" } }
äŸåæ§æ³šå ¥ãšãã©ã¡ãŒã¿ãŒã¢ãã«
ã³ã³ã¹ãã©ã¯ã¿ãŒæ³šå ¥ã¯ãæãäžè¬çãªäŸåæ§æ³šå ¥ã¢ãããŒãã®1ã€ã§ãã ASP.NET Coreã¯ãœãªã¥ãŒã·ã§ã³ã§ã³ã³ã¹ãã©ã¯ã¿ãŒã€ã³ãžã§ã¯ã·ã§ã³ã䜿çšãããããããã䜿çšããŸãã ããŒã¿ããŒã¹ã«æ¥ç¶ããããã®ãã©ã¡ãŒã¿ãŒããããããã«ã¯ãæ°ããã¯ã©ã¹ã®èšå®ãè¿œå ããŸãã
namespace NotebookAppApi.Model { public class Settings { public string ConnectionString; public string Database; } }
Startup.csãã¡ã€ã«ã®ConfigureSettingsã¡ãœãããå€æŽããŠããã©ã¡ãŒã¿ãŒã¢ã¯ã»ã¹ã¢ãã«ã«èšå®ãè¿œå ããŸãã å°æ¥çã«ã¯ãIOptionsã€ã³ã¿ãŒãã§ã€ã¹ã䜿çšããŠèšå®ã«ã¢ã¯ã»ã¹ããŸãã
public void ConfigureServices(IServiceCollection services) { // Add framework services. services.AddMvc(); services.Configure<Settings>(options => { options.ConnectionString = Configuration.GetSection("MongoConnection:ConnectionString").Value; options.Database = Configuration.GetSection("MongoConnection:Database").Value; }); }
MongoDB .NETãã©ã€ããŒ
MongoDBã«æ¥ç¶ããã«ã¯ãMongoDB.Driverãšããããã±ãŒãžãNugetãããžã§ã¯ãã«è¿œå ããŸãã ããã¯ãASP.NET Coreã§ã¢ããªã±ãŒã·ã§ã³ãå®å šã«ãµããŒããã.NETã®å ¬åŒãã©ã€ããŒã§ãã
ã¢ãã«
ããŒãããã¯ã®åããŒãã説æããã¯ã©ã¹ã¢ãã«ïŒPOCOïŒã以äžã«ç€ºããŸãã
using System; using MongoDB.Bson.Serialization.Attributes; namespace NotebookAppApi.Model { public class Note { [BsonId] public string Id { get; set; } public string Body { get; set; } = string.Empty; public DateTime UpdatedOn { get; set; } = DateTime.Now; public DateTime CreatedOn { get; set; } = DateTime.Now; public int UserId { get; set; } = 0; } }
ããŒã¿ããŒã¹ã³ã³ããã¹ã
NoteContextã¯ã©ã¹ã«äœæ¥åäœãã¿ãŒã³ãå®è£ ããŸãã
public class NoteContext { private readonly IMongoDatabase _database = null; public NoteContext(IOptions settings) { var client = new MongoClient(settings.Value.ConnectionString); if (client != null) _database = client.GetDatabase(settings.Value.Database); } public IMongoCollection Notes { get { return _database.GetCollection("Note"); } } }
ãªããžããª
ãªããžããªã€ã³ã¿ãŒãã§ã€ã¹ã䜿çšããŠãã¡ã¢ã®ç®¡çã«å¿ èŠãªæ©èœãå®è£ ããŸãã ãŸããã¢ããªã±ãŒã·ã§ã³ïŒã³ã³ãããŒã©ãŒã»ã¯ã·ã§ã³ãªã©ïŒã«ç°¡åã«ã¢ã¯ã»ã¹ã§ããããã«ãäŸåæ§æ³šå ¥ïŒDIïŒã䜿çšããŸãã
public interface INoteRepository { Task<IEnumerable<Note>> GetAllNotes(); Task<Note> GetNote(string id); Task AddNote(Note item); Task<DeleteResult> RemoveNote(string id); // (body) Task<UpdateResult> UpdateNote(string id, string body); }
ããŒã¿ããŒã¹ãžã®ã¢ã¯ã»ã¹ã¯éåæã«ãªããŸãã å®å šãªéåæã¹ã¿ãã¯ãè¿œå ãããããŒãžã§ã³2.0以äžã®ãã©ã€ããŒã䜿çšããŸãã äŸãšããŠããã¹ãŠã®ã¡ã¢ãååŸããããã«ãéåæãªã¯ãšã¹ããäœæããŸãã
public async Task<IEnumerable<Note>> GetAllNotes() { return await _context.Notes.Find(_ => true).ToListAsync(); }
以äžã¯ãåºæ¬çãªCRUDæäœã®å®å šãªå®è£ ã§ãã
namespace NotebookAppApi.Data { public class NoteRepository : INoteRepository { private readonly NoteContext _context = null; public NoteRepository(IOptions<Settings> settings) { _context = new NoteContext(settings); } public async Task<IEnumerable<Note>> GetAllNotes() { return await _context.Notes.Find(_ => true).ToListAsync(); } public async Task<Note> GetNote(string id) { var filter = Builders<Note>.Filter.Eq("Id", id); return await _context.Notes .Find(filter) .FirstOrDefaultAsync(); } public async Task AddNote(Note item) { await _context.Notes.InsertOneAsync(item); } public async Task<DeleteResult> RemoveNote(string id) { return await _context.Notes.DeleteOneAsync( Builders<Note>.Filter.Eq("Id", id)); } public async Task<UpdateResult> UpdateNote(string id, string body) { var filter = Builders<Note>.Filter.Eq(s => s.Id, id); var update = Builders<Note>.Update .Set(s => s.Body, body) .CurrentDate(s => s.UpdatedOn); return await _context.Notes.UpdateOneAsync(filter, update); } } }
DIã¢ãã«ã䜿çšããŠNoteRepositoryã«ã¢ã¯ã»ã¹ããã«ã¯ãConfigureServicesã«è¡ãè¿œå ããŸãã
services.AddTransient<INoteRepository, NoteRepository>();
ããã§ïŒ
- AddTransientã¯ããªããžããªãæ¯ååäœæãããããšãæå³ããŸãã
- AddScoped-ãªã¯ãšã¹ãããšã«1åã®ã¿ã
- AddSingleton-æåã®èŠæ±ã§1åã åŸç¶ã®åãªã¯ãšã¹ãã¯ãæåã«äœæãããã€ã³ã¹ã¿ã³ã¹ã䜿çšããŸãã
ã¡ã€ã³ã³ã³ãããŒã©ãŒ
以äžã¯ããµãŒãããŒãã£ã®ã¢ããªã±ãŒã·ã§ã³ã§å©çšå¯èœãªãã¹ãŠã®CRUDã¡ãœãããå®è£ ãããŠããWeb APIã¢ããªã±ãŒã·ã§ã³ã®ã¡ã€ã³ã³ã³ãããŒã©ãŒã®ã³ãŒãã§ãã
泚 ïŒGetã¡ãœããã¯NoCacheå±æ§ã§ããŒã¯ãããŠãããWebã¯ã©ã€ã¢ã³ããåžžã«ãµãŒããŒã«ãªã¯ãšã¹ããéä¿¡ããããã«ããŸãã
namespace NotebookAppApi.Controllers { [Produces("application/json")] [Route("api/[controller]")] public class NotesController : Controller { private readonly INoteRepository _noteRepository; public NotesController(INoteRepository noteRepository) { _noteRepository = noteRepository; } [NoCache] [HttpGet] public Task<IEnumerable<Note>> Get() { return GetNoteInternal(); } private async Task<IEnumerable<Note>> GetNoteInternal() { return await _noteRepository.GetAllNotes(); } // GET api/notes/5 [HttpGet("{id}")] public Task<Note> Get(string id) { return GetNoteByIdInternal(id); } private async Task<Note> GetNoteByIdInternal(string id) { return await _noteRepository.GetNote(id) ?? new Note(); } // POST api/notes [HttpPost] public void Post([FromBody]string value) { _noteRepository.AddNote(new Note() { Body = value, CreatedOn = DateTime.Now, UpdatedOn = DateTime.Now }); } // PUT api/notes/5 [HttpPut("{id}")] public void Put(string id, [FromBody]string value) { _noteRepository.UpdateNoteDocument(id, value); } // DELETE api/notes/23243423 [HttpDelete("{id}")] public void Delete(string id) { _noteRepository.RemoveNote(id); } } }
ããŒã¿ã®åæå
ãã®ããŒãã§ã¯ããã¢ã³ã¹ãã¬ãŒã·ã§ã³ã®ã¿ãç®çãšããŠç®¡çã¿ã¹ã¯ãå®è¡ããããã«èšèšãããã³ã³ãããŒã©ãŒãå®è£ ããŸãïŒãããŒããŒã¿ã䜿çšããŠããŒã¿ããŒã¹ãåæåããããã«äœ¿çšããŸãïŒã
Initã¡ãœããã1ã€å®è£ ããŸãããã®ã¡ãœããã¯ãå¿ èŠãªãã¹ãŠã®ãã¹ãããŒã¿ãããŒã¿ããŒã¹ã«äœæããŠå ¥åããŸãã ã¡ãœããã¯httpïŒ// localhostïŒ5000 / api / system / initãŸãã¯httpïŒ// localhostïŒ53617 / api / system / init ïŒIISã䜿çšããå ŽåïŒã§å©çšã§ããŸãã å®éã«ã¯ããã®ãããªã³ã³ãããŒã©ãŒã¯æ¬æ Œçãªã管çããã«ãã«é²åããå¯èœæ§ããããŸãã
[Route("api/[controller]")] public class SystemController : Controller { private readonly INoteRepository _noteRepository; public SystemController(INoteRepository noteRepository) { _noteRepository = noteRepository; } // Call an initialization - api/system/init [HttpGet("{setting}")] public string Get(string setting) { if (setting == "init") { _noteRepository.RemoveAllNotes(); _noteRepository.AddNote(new Note() { Id = "1", Body = "Test note 1", CreatedOn = DateTime.Now, UpdatedOn = DateTime.Now, UserId = 1 }); _noteRepository.AddNote(new Note() { Id = "2", Body = "Test note 2", CreatedOn = DateTime.Now, UpdatedOn = DateTime.Now, UserId = 1 }); _noteRepository.AddNote(new Note() { Id = "3", Body = "Test note 3", CreatedOn = DateTime.Now, UpdatedOn = DateTime.Now, UserId = 2 }); _noteRepository.AddNote(new Note() { Id = "4", Body = "Test note 4", CreatedOn = DateTime.Now, UpdatedOn = DateTime.Now, UserId = 2 }); return "Done"; } return "Unknown"; } }
èµ·åèšå®
ãããžã§ã¯ãã®éå§æã«ãµãŒããŒãžã®ãªã¯ãšã¹ãã®çµæã衚瀺ããã«ã¯ãLaunchSettings.jsonãã¡ã€ã«ãæŽæ°ããŸã
以äžã¯ãURLãããã©ã«ãã§èµ·åããããã¹ãŠã®ã¡ã¢ïŒapi / notesïŒã衚瀺ãããèšå®ã®äŸã§ãã
{ "iisSettings": { "windowsAuthentication": false, "anonymousAuthentication": true, "iisExpress": { "applicationUrl": "http://localhost:53617/", "sslPort": 0 } }, "profiles": { "IIS Express": { "commandName": "IISExpress", "launchBrowser": true, "launchUrl": "api/notes", "environmentVariables": { "ASPNETCORE_ENVIRONMENT": "Development" } }, "NotebookAppApi": { "commandName": "Project", "launchBrowser": true, "launchUrl": "http://localhost:5000/api/notes", "environmentVariables": { "ASPNETCORE_ENVIRONMENT": "Development" } } } }
ãããžã§ã¯ãã®éå§
ãããžã§ã¯ããéå§ããåã«ãMongoDBãå®è¡ãããŠããããšã確èªããŸãïŒWindowsãµãŒãã¹ãšããŠããŸãã¯äžèšã§è¡ãããã³ãã³ãã©ã€ã³ããïŒã
ã¢ããªã±ãŒã·ã§ã³ãæåã«èµ·åãããšããã¹ãŠã®ãšã³ããªãå«ãããŒãžã«ãªãã€ã¬ã¯ããããŸããã åæåããã»ã¹ã¯ãŸã éå§ãããŠããªãããããã®ããŒãžã«ã¯ç©ºã®ã»ããã衚瀺ãããŸãã
ã³ãã³ããå®è¡ããŠããŒã¿ããŒã¹ãåæåãã ã¢ãã¬ã¹ã«ç§»åããŠãã¹ãããŒã¿ãå ¥åããŸã ã
次ã«ãã¢ããªã±ãŒã·ã§ã³ã®éå§ããŒãžã«æ»ããããŒã¿ã衚瀺ãããããšã確èªããŸãã
ããã¢ã³ãŽã䜿çšãã
Robomongoã䜿çšãããšãããŒã¿ããŒã¹å ã®ã¬ã³ãŒãã確èªã§ããŸãã è³æ Œæ å ±ã䜿çšããŠããŒã¿ããŒã¹ã«æ¥ç¶ãããšã4ã€ã®ãšã³ããªãã¹ãŠã確èªã§ããŸãã
äŸå€åŠç
asyncããã³awaitããŒã¯ãŒããCïŒ5.0ã§å°å ¥ãããTPLïŒã¿ã¹ã¯äžŠåã©ã€ãã©ãªïŒã®äœ¿çšãç°¡çŽ åãããŸããã try / catchãããã¯ã䜿çšããŠãäŸå€ããã£ããããã ãã§ããPublic async Task <IEnumerable> GetAllNotesïŒïŒ
{ try { return await _context.Notes.Find(_ => true).ToListAsync(); } catch (Exception ex) { // log or manage the exception throw; } }
ãããã£ãŠãTaskã®éåæã€ã³ã¹ã¿ã³ã¹ã§ãšã©ãŒãåŠçã§ããŸãããããã«åŠçããããã«äžèšã®äŸå€ãã¹ããŒã§ããŸãã
MongoDBããã¥ã¡ã³ãã®å®å šãªæŽæ°
æåã®ãããžã§ã¯ãäŸã§ã¯ãæŽæ°æ©èœã¯éžæçãªããããã£æŽæ°ã®ååã«åºã¥ããŠæ©èœããŠããŸããã
ReplaceOneAsyncã¡ãœããã䜿çšããŠãããã¥ã¡ã³ããå®å šã«æŽæ°ã§ããŸãã IsUpsertãã©ã¡ãŒã¿ãŒã¯ãããŒã¿ããŒã¹ã«ããã¥ã¡ã³ãããªãå Žåã¯äœæããå¿ èŠãããããšã瀺ããŸãã
public async Task<ReplaceOneResult> UpdateNote(string id, Note item) { return await _context.Notes .ReplaceOneAsync(n => n.Id.Equals(id) , item , new UpdateOptions { IsUpsert = true }); }
ã¯ãã¹ãã¡ã€ã³ãªã¯ãšã¹ãèšå®ïŒCORSïŒ
ç°ãªããã¡ã€ã³ã§å®è¡ãããŠããã¢ããªã±ãŒã·ã§ã³ã䜿çšããã«ã¯ãASP.NET Web APIãœãªã¥ãŒã·ã§ã³ã§ã¯ãã¹ãã¡ã€ã³ãªã¯ãšã¹ãåŠçïŒCORSïŒãæå¹ã«ããå¿ èŠããããŸãã ããšãã°ãã¡ã€ã³èŠæ±ã®åã®Angular 2ã¯äºåãã§ãã¯èŠæ±ãæåã«å®è¡ããŸããããã¯ãã¯ãã¹ãã¡ã€ã³èŠæ±ãèš±å¯ãããŠãããã©ããã®ãã§ãã¯ãšããŠæ©èœããŸãã æåã«ãStartup.csãã¡ã€ã«ã®ConfigureServicesã¡ãœããã§CORSæ©èœãç»é²ããŸãã
public void ConfigureServices(IServiceCollection services) { // Add service and create Policy with options services.AddCors(options => { options.AddPolicy("CorsPolicy", builder => builder.AllowAnyOrigin() .AllowAnyMethod() .AllowAnyHeader() .AllowCredentials()); }); // .... services.AddMvc(); }
次ã«ãConfigureã¡ãœããã§app.useCorsã¡ãœãããåŒã³åºããŠãã¢ããªã±ãŒã·ã§ã³ã®åãªã¯ãšã¹ãã«å¯ŸããŠããªã·ãŒãã°ããŒãã«ã«æå¹ã«ããŸãã
public void Configure(IApplicationBuilder app) { app.UseCors("CorsPolicy"); app.UseMvc(); }
ãã¡ã€ã«ãæäœãã
ãã€ããªãã¡ã€ã«ãMongoDBããã¥ã¡ã³ãã«ä¿åããããšãã§ããŸãããMongoDB 2.xã®æ倧ããã¥ã¡ã³ããµã€ãºã¯16 MBã§ãïŒä»¥åã®ããŒãžã§ã³ã§ã¯4 MBã®ã¿ïŒã ãããã£ãŠã倧éã®æ å ±ãç¹ã«å€§ããªãã¡ã€ã«ãä¿åããããã«ãMongoDBã¯GridFSã·ã¹ãã ã䜿çšããŸãã GridFSã¯ãMongoDBã«ä»»æã®ãµã€ãºã®ãã¡ã€ã«ãä¿åããããã®èŠåã§ããããã¹ãŠã®å ¬åŒãã©ã€ããŒã§ãµããŒããããŠããŸãã ããŒã¿ããŒã¹å ã®ãã¡ã€ã«ã¯ãéåžžãfs.filesãããã³ãfs.chunksããšåŒã°ãã2ã€ã®ã³ã¬ã¯ã·ã§ã³ã«ä¿åãããŸãã ã¢ããããŒããããåãã¡ã€ã«ã«ã¯ããfs.filesãã³ã¬ã¯ã·ã§ã³ã«1ã€ã®ããã¥ã¡ã³ããããããã¡ã€ã«ã«é¢ããæ å ±ãšããfs.chunksãã³ã¬ã¯ã·ã§ã³å ã®å€ãã®ããã¥ã¡ã³ãããŒã¹ïŒãã£ã³ã¯ïŒãå«ãŸããŸãã
ãŸããNuGetãä»ããŠãã©ã€ããŒçšã®GridFSã³ã³ããŒãã³ããè¿œå ããå¿ èŠããããŸãã
次ã«ã GridFSBucketã¯ã©ã¹ã®ãªããžã§ã¯ããã³ã³ããã¹ãã«è¿œå ããå¿ èŠããããŸãã GridFSBucketã¯ãã³ã¬ã¯ã·ã§ã³ãfs.filesããšãfs.chunksãã®äžçš®ã§ããGridFSãæäœããããã®éèŠãªãªããžã§ã¯ãã§ããããã¹ãŠã®ãã¡ã€ã«ãä¿åã§ããããã±ãããã§ãã
_database = client.GetDatabase(settings.Value.Database); _bucket = new GridFSBucket(_database);
è¿œå ã®ãã©ã¡ãŒã¿ãŒãæå®ããããšãã§ããŸãã ããšãã°ãã³ã¬ã¯ã·ã§ã³ã®ååïŒãã¬ãã£ãã¯ã¹ãfsãã®ä»£ããã«èªåã®ååã«ãªããŸãïŒããã³1ã€ã®ãã£ã³ã¯ã®ãµã€ãºã
_database = client.GetDatabase(settings.Value.Database); var gridFSBucketOptions = new GridFSBucketOptions() { BucketName = "images", ChunkSizeBytes = 1048576, // 1 }; _bucket = new GridFSBucket(_database, gridFSBucketOptions);
GridFSBucketã€ã³ã¹ã¿ã³ã¹ã䜿çšããæ©èœãè¿œå ããŸãã
public GridFSBucket Bucket { get { return _bucket; } }
ãŸãã¯ãããçãè¡šèšã䜿çšã§ããŸãã
public GridFSBucket Bucket => _bucket;
次ã«ãæ©èœãæŽæ°ããŸãã NoteRepository.csã®ããŒã¿ããŒã¹ã«ãã¡ã€ã«ãè¿œå ããã¡ãœãããè¿œå ããŸã
public async Task<ObjectId> UploadFile(IFormFile file) { try { var stream = file.OpenReadStream(); var filename = file.FileName; return await _context.Bucket.UploadFromStreamAsync(filename, stream); } catch (Exception ex) { return new ObjectId(ex.ToString()); } }
泚ïŒãããã®ã³ã¬ã¯ã·ã§ã³ã«çŽæ¥ã¢ã¯ã»ã¹ããã®ã§ã¯ãªããåžžã«GridFSBucketãªããžã§ã¯ãã䜿çšããŠGridFSã³ã¬ã¯ã·ã§ã³ïŒãfs.chunksãããã³ãfs.filesãïŒãšå¯Ÿè©±ããå¿ èŠããããŸãã
INoteRepository.csã«ã¡ãœããã·ã°ããã£ãè¿œå ããŸãã
Task<ObjectId> UploadFile(IFormFile file);
POSTã¡ãœãããè¿œå ããŠãNotesController.csãæŽæ°ããŸãã
// POST api/notes/uploadFile [HttpPost("uploadFile")] public async Task<ObjectId> UploadFile(IFormFile file) { return await _noteRepository.UploadFile(file); }
泚ïŒããããŒContent-TypeïŒmultipart / form-dataïŒããããã¡ã€ã«ã®è»¢éæ¹æ³ã§ãïŒã§éä¿¡ãããããŒã¿ãæ£ããåŠçããã«ã¯ããã®ã¿ã€ãã®ããŒã¿ã®ãµããŒããè¿œå ããå¿ èŠããããŸãã ãããè¡ãã«ã¯ãNotesControllerã³ã³ãããŒã©ãŒã¯ã©ã¹ã«å¯Ÿå¿ããConsumeså±æ§ãè¿œå ããŸãã
[Consumes("application/json", "multipart/form-data")] public class NotesController : Controller
ãã¡ã€ã«IDã§ååãè¿ãç°¡åãªã¡ãœããã®äŸã䜿çšããŠããã¡ã€ã«ã«é¢ããæ å ±ãååŸããããšãæ€èšããŸãã
public async Task<String> GetFileInfo(string id) { GridFSFileInfo info = null; var objectId = new ObjectId(id); try { using (var stream = await _context.Bucket.OpenDownloadStreamAsync(objectId)) { info = stream.FileInfo; } return info.Filename; } catch (Exception) { return "Not Found"; } }
APIãã芧ãã ãã
Web APIããã¹ãããã«ã¯ã Postmanã䜿çšããŸãã ããšãã°ãIDïŒapi / notes / 2ïŒã§ã¬ã³ãŒããååŸããããã«ãã§ãã¯ããŸããGETãªã¯ãšã¹ãã¿ã€ããéžæããŠãURLïŒhttpïŒ// localhostïŒ53617 / api / notes / 2ïŒãå ¥åããããããŒïŒContent-TypeïŒapplication / jsonïŒãè¿œå ããŸãã ãªã¯ãšã¹ããéä¿¡ããåŸãId = 2ã®ã¬ã³ãŒãã«é¢ããæ å ±ã®åœ¢åŒã§ã¬ã¹ãã³ã¹ãååŸããŸãã
ãã®ãšã³ããªã®å 容ãå€æŽããŸãã ãããè¡ãã«ã¯ãèŠæ±ã¿ã€ããPUTã«å€æŽãã[ããã£]> [æªå å·¥]ã¿ãã«ç§»åããŠãã¬ã³ãŒãã®æ°ããã³ã³ãã³ããèšå®ããŸãã
ãã®åŸãRoboMongoã«ç§»åããŠãã¬ã³ãŒãã®å€ãæŽæ°ãããããšã確èªããŸãã
GridFSã¡ã«ããºã ã®åäœã確èªããŸãããã ãããè¡ãã«ã¯ãContent-Typeãmultipart / form-dataã«å€æŽããURLãlocalhost ïŒ53617 / api / notes / uploadFileãšããŠèšå®ããBody> form-dataã»ã¯ã·ã§ã³ã§ãã¡ã€ã«ãè¿œå ããŠéä¿¡ããŸãã å¿çãšããŠããã®ãã¡ã€ã«ã«é¢ããæ å ±ãåãåããŸããã
ãã®åŸããimages.filesãããã³ãimages.chunksãã³ã¬ã¯ã·ã§ã³å ã®ãã®ãã¡ã€ã«ã«å¯Ÿå¿ããã¬ã³ãŒããäœæãããŸããã
IDã§ãã¡ã€ã«åãååŸããç°¡åãªæ¹æ³ã確èªããŸãããã ãããè¡ãã«ã¯ãã¢ãã¬ã¹ããŒã«ãã¡ã€ã«IDã転éããŠãéåžžã®GETãªã¯ãšã¹ããäœæããŸãã
ãããã«
MongoDBããŒã ãéçºè ã®å©äŸ¿æ§ãšæçšæ§ã«ååãªæ³šæãæãã ãã¬ãŒãã³ã°ã³ãŒã¹ãå®æœãã ã³ãã¥ããã£ã®æèŠã«ç©æ¥µçã«é¢å¿ãæã¡ã åé¡ãè¿ éã«è§£æ±ºããŠãããšããäºå®ïŒãããžã§ã¯ãã¯ãã©ã³ãã£ã¢ã ãã§ãªããåžžå€è ã®äŒç€Ÿã«ãã£ãŠãæžãããŠããŸãïŒã¯ãMongoDBæ°ããæ©äŒãå°å ¥ãæ¹åããããã®åªããããŒã¹ãç¶æãç¶ããŸãã
ãããŠãMongoDBãWindowsã ãã§ãªããååãªãã©ã€ããŒã®æç床ãšLinuxããã³MacOSã§ã®.NET Coreã®ãµããŒãã«é¢ããMicrosoftã®ã³ãŒã¹ãšå ±ã«å±éã§ãããšããäºå®ã¯ãããšãã°ããœãªã¥ãŒã·ã§ã³ãLinuxã«å®å šã«å±éãããå Žåãæçœãªãã©ã¹ã§ãã ãã ããSQL Server 2017ã®ãªãŒãã³ãã¹ãã«ã€ããŠèšåãããããããŸããããã®ãœãªã¥ãŒã·ã§ã³ã¯Linuxã«ãå±éã§ããŸãã ãããŠããããžã§ã¯ããéçºãããšãã«äœ¿çšããå¿ èŠãããã¢ãããŒãã®éžæïŒNoSQLãŸãã¯RDBMS-äž»ã«ã¢ããªã±ãŒã·ã§ã³ã®è©³çŽ°ã«äŸåããŸãã MongoDBã¯ãããŒã¿ãæäœããããã®ãã¹ãŠã®ã·ããªãªãé©åããå°æ¥çã«äž»èŠãªãµã³ãã«ã«é©åããã³ã¬ã¯ã·ã§ã³å šäœãååŸããå Žåã«çæ³çã§ãã ãã®ãããªç¢ºå®æ§ããªãå Žåã¯ãããã«RDBMSã䜿çšããããšããå§ãããŸãã
ãœãŒã¹ïŒ