Ebben a leckében arról lesz szó, hogyen kössük össze az 1/4-es leckében készített API-t egy állandó tárolóval. Valahogy így:
Korábban már volt erről szó, de akkor CosmosDb-vel. Ezt fogjuk most lecserélni MongoDb-re. Úgy találtam, hogy a CosmosDb-nek van néhány hátránya, amivel nem tudok együtt élni:
- az ingyenes vonalon sok minden le van korlátozva, ezért aztán egy az egyben nem lehet újra használni a kódot, amikor a felhőbe szeretnénk majd költöztetni az alkalmazást.
- Az is problémát jelent, hogy (legalábbis számomra) maga az adatbázis használata sem elég intuitív.
- Harmadik érvként pedig az elterjedtséget tudom felhozni. A MongoDb egy sokkal elterjedtebb megoldás. Ezért fogjuk most kipróbálni ezt, és összekötni az API-val.
Postman | The Collaboration Platform for API Development
1., Szerezzük be az eszközöket
A MongoDb-t egy community serverről fogjuk egyelőre futtatni, ami azt jelenti, hogy az adatbázis, és a hozzáférési réteg is a mi gépünkön lesz.
MongoDB Community Download | MongoDB
Windows install
- Installáld fel az msi-t
- A környezeti változók között add hozzá a mongo elérési útvonalá
- A C meghajtón hozz létre egy data könyvtárat, ebben pedig egy db könyvtárat. A mongo ezt használja default-ként arra, hogy hol tárolja az adatokat
- Indítsd el a szervert
- Indíts el egy parancssort, és írd be, hogy
mongod.exe --dbpath "C:\data"Ez kiír egy csomó szöveget, amelynek az utolsó sora
"ctx":"listener","msg":"Waiting for connections","attr":{"port":27017,"ssl":"off"}}
- Ezután indíts el mégegy parancssort
mongo.exe
- Ekkor a következőket kell látnod (én ConEmu-t használok ezért ilyen szép)
Ubuntu install
A MongoDb Ubuntura is könnyen installálható. Lásd az alábbi linket.Első lépések
db.getCollection('testData').find({})
2., Kössük be az API-t
private readonly IMongoClient _mClient;private readonly IMongoDatabase _db;
public class MongoDbService { private readonly IMongoClient _mClient; private readonly IMongoDatabase _db; public MongoDbService(IConfiguration configuration) { var dbUri = configuration.GetSection("AppSettings") .GetSection("DbUri").Value; var databaseId = configuration.GetSection("AppSettings") .GetSection("DatabaseId").Value; //string dbUri = "mongodb://localhost"; _mClient = new MongoClient(dbUri); var dbList = _mClient.ListDatabases().ToList(); if (dbList.Select(d => d.ToString()).Contains(databaseId)) { Console.WriteLine($"Error: databse {databaseId} was not found on Uri {dbUri}"); } _db = _mClient.GetDatabase(databaseId); } }
public IMongoDatabase GetDb() { return _db; } public IMongoClient GetClient() { return _mClient; }
És hogy mi a trutymák azaz "I" a típusnevek előtt? Ez jelöli, hogy ez a típus valójában egy interface. Az interface (interfész) egy limitált hozzáférést biztosít egy osztály funkcionalitásához. Valami olyasmi, mint amikor az okosóra gyártó cég nem a nyomtatott áramkört adja oda a kezedbe, hanem egy becsomagolt terméket, amin van 2 gomb meg egy touchscreen. Nem látod azt, hogy hogyan alakítja a mozgást elektromos árammá a kütyü, amit aztán egy memóriában adatként eltárol, hogy később az antennát vezérelve a wifidre kapcsolódva feltöltse a felhős fiókodba. Ezt nem is kell látnod. Elég, ha megnyomod a megosztás gombot. Az okosóra interface-e neked csak a "edzés indítása" meg a "megosztás" gombot jelenti.
Hasonló módon ez a 2 metódus az adatbázishoz illetve a klienshez fog limitált hozzáférést biztosítani. A többi részletet mi is el szeretnénk rejteni, ezért a mi osztályunkat (MongoDbService) is egy interface-en keresztül fogjuk elérhetővé tenni más komponensek számára. Szerencsére ez visual studio-ban egyszerű.
Álljunk a kurzorral az osztály nevére, és gondolom sejted melyik billentyűket kell lenyomni. Ctrl + . Ezután válaszd az extract interface opciót, majd a felugró modal-on ok, és csiribi-csiribá.
Nézzük meg ezután hogy érjünk el egy collection-t a MongoDb-ből. A ValuesController.cs-ben vegyük a sima HttpGet metódus-t és írjuk be a következő kódot. Először is hozzunk létre egy konstruktort a ValuesController osztálynak a ctor kulcszóval, mint az előbb a service-ben.
Ezután adjunk hozzá egy bemenő paramétert IMongoDbService (az előbb létrehozott interface-t), Ctrl+.-tal hivatkozzuk be a namespace-t (using RestApiTest.Services). Ezután pedig ismét menjünk rá a bemenő paraméterre, és Ctrl+.-tal hozzunk létre egy field-et az osztályon.
A Visual studio egyből felismeri, hogy ezt a változót inicializálni szeretnénk a bemenő paraméterre. Meg is teszi helyettünk.
Ezután már csak meg kell hívni a service megfelelő metódusát, és lekérni a collection-t.
[HttpGet] public ActionResult<IEnumerable<string>> Get() { _mongoDbService.GetDb().GetCollection<>("newCollection"); }
Mivel azonban a .Net típusos nyelv, ezért a GetCollection-nek egy típus paramétert is át kell adni, ha F12-t nyomunk a GetCollection kijelölése után, akkor a keretrendszer (VS) kiadja nekünk hogyan kéne meghívnunk ezt a metódust.
Hozzunk hát létre egy ún. model osztályt, amiben ezeket az adatokat fogjuk átadni.(Person.cs). A property-ket úgy adhatjuk meg legegyszerűbben, hogy beírjuk, hogy "prop" majd kétszer megnyomjuk a tab-ot, ezután beírjuk a property nevét. Egyelőre 3 property-t hozzunk létre Name, Age, Occupation.
// GET api/values [HttpGet] public ActionResult<IEnumerable<Person>> Get() { var coll = _mongoDbService.GetDb().GetCollection<Person>("testData"); var people = coll.Find(p => true).ToList(); return people; }
A szükséges namespace-eket Ctrl+.-al tudjuk behivatkozni. Az első sor lekéri a megfelelő collection-t. A második so pedig lekéri a collection-ben lévő Person objektumokat. a "p => true" kifejezés egy szűrő, ami azt a feltételt adja meg, hogy melyik objektumokat adja vissza (jelenleg az összeset).
Ha most F5-öt nyomunk, akkor megnyílik a böngésző és hupsz ? Na mi ez már megint?
A keretrendszer nem tudta betölteni a values controller-t mert nem találja a service-t, amit létrehoztunk. Hát persze, mert hogy nem adtuk meg a keretrendszernek, hogy hol találja. Állítsuk le a programunkat, nyissuk meg a Startup.cs fájlt, és adjuk hozzáa a ConfigureServices metódushoz a következő kódot.
services.AddScoped<IMongoDbService, MongoDbService>();
Ez a sor megadja, hogy ha a keretrendszer az IMongoDbService interface-t látja, akkor melyik objektumot hozza létre. Jelen esetben a MongoDbService osztály egy példányát.
// This method gets called by the runtime. Use this method to add services to the container. public void ConfigureServices(IServiceCollection services) { services.AddScoped<IMongoDbService, MongoDbService>(); services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1); }
Majdnem. Ha most F5-öt nyomunk, akkor ezt a hibaüzenetet kapjuk
Az a gond, hogy az adatbázis által létrehozott _id nincs rajta a modell objektumunkon. Módosítsuk a Person osztályt.
public class Person { [BsonElement("_id")] public ObjectId Id { get; set; } [BsonElement("name")] public string Name { get; set; } [BsonElement("age")] public int Age { get; set; } [BsonElement("occupation")] public string Occupation { get; set; } }
A BsonElement-ekre azért van szükség, mert az adatbázisban kisbetűs, míg a modell osztályban nagybetűs property nevekkel tároljuk az adatokat (ugyanis .NET-ben az utóbbi a konvenció). Újabb F5 után.
Most már csak a többi CRUD (Create Read Update Delete) művelet kell megvalósítani. Minden beírt kód után újra kell fordítani, és indítani az alkalmazást F5-tel, ahhoz hogy a változások érvénybe lépjenek.
// GET api/values/5 [HttpGet("{id}")] public ActionResult<Person> Get(string id) { var coll = _mongoDbService.GetDb().GetCollection<Person>("testData"); var person = coll.Find(p => p.Id == new MongoDB.Bson.ObjectId(id)).FirstOrDefault(); return person; }
// POST api/values [HttpPost] public ActionResult Post([FromBody] Person person) { var coll = _mongoDbService.GetDb().GetCollection<Person>("testData"); try { coll.InsertOne(person); return Ok("success"); } catch (Exception ex) { return new ObjectResult(500) { Value = ex.ToString(), StatusCode = 500 }; } }
[HttpDelete("{id}")] public ActionResult Delete(string id) { var coll = _mongoDbService.GetDb().GetCollection<Person>("testData"); try { coll.DeleteOne(p => p.Id == new MongoDB.Bson.ObjectId(id)); return Ok("success"); } catch (Exception ex) { return new ObjectResult(500) { Value = ex.ToString(), StatusCode = 500 }; } }
// PUT api/values/5 [HttpPut("{id}")] public ActionResult Put(string id, [FromBody] Person person) { var coll = _mongoDbService.GetDb().GetCollection<Person>("testData"); try { person.Id = new MongoDB.Bson.ObjectId(id); coll.ReplaceOne(p => p.Id == new MongoDB.Bson.ObjectId(id), person); return Ok("success"); } catch (Exception ex) { return new ObjectResult(500) { Value = ex.ToString(), StatusCode = 500 }; } }
További infók
Hogy tetszik a blog? (google.com)
Nincsenek megjegyzések:
Megjegyzés küldése