Mobiele apps programmeren met Xamarin – Entity Framework – CRUD

print

Deze handleiding maakt deel uit van het programmeertraject:


Inhoud


Wat vooraf ging


Inleiding

CRUD staat voor:

  • Create: records toevoegen
  • Read: records selecteren
  • Update: records wijzigen
  • Delete: records verwijderen

In deze handleiding bespreken we CRUD met Entity Framework.

We vertrekken vanuit onderstaande, reeds gekende, entiteiten Blog en Post en de onderlinge relatie.

public class Blog
{
    public int BlogId { get; set; }
    public string Url { get; set; }

    public List<Post> Posts { get; set; }
}

public class Post
{
    public int PostId { get; set; }
    public string Title { get; set; }
    public string Content { get; set; }

    public int BlogId { get; set; }
    public Blog Blog { get; set; }
}

Using

Om eventuele fouten op te vangen gaan we gebruik maken van het using-statement.

Het using-statement roept automatisch een dispose-statement aan en dit zorgt ervoor dat de ongebruikte resources, ook als het fout loopt, worden “opgekuist”, vrijgegeven.

Het is een goede gewoonte om alle databankbewerkingen te plaatsen binnen een using-statement, maar u moet het dan wel consequent overal doen of u genereert fouten.

using (var context = new BloggingContext())
{
    …
}

Create (toevoegen)

Gegevens aan een entiteit toevoegen kan als volgt:

using (var context = new BloggingContext())
{
    var blog = new Blog { Name="Test", Url = "http://test.com" };
    context.Blogs.Add(blog);
    context.SaveChanges();
}
  • Maak gebruik van een using-statement om ongebruikte resources op te kuizen.
  • Er wordt een nieuwe instantie van de DbContext genomen: var context = new BloggingContext().
  • Er wordt een nieuwe blog aangemaakt en deze krijgt de gewenste waarden: var blog = new Blog { Name="Test", Url = "http://test.com" };.
  • Deze nieuwe Blog wordt toegevoegd aan (de entiteit/tabel) Blogs: context.Blogs.Add(blog);.
  • De DbContext/databank wordt bewaard: context.SaveChanges();

Uiteraard kunnen de waarden ook gelezen worden uit bv. tekstvakken: var blog = new Blog { Name = BlogNaam.Text, Url = BlogURL.Text" };.

Gerelateerde entiteiten

Indien nodig kan ook in één beweging gerelateerde gegevens worden toegevoegd.

using (var context = new BloggingContext())
{
    var blog = new Blog
    {
        Name = ".NET",
        Url = "http://test.com/dotnet",
        Posts = new List<Post>
        {
            new Post { Title = "Intro to C#" },
            new Post { Title = "Intro to VB.NET" },
            new Post { Title = "Intro to F#" }
        }
    };

    context.Blogs.Add(blog);
    context.SaveChanges();
}

Merk op dat het toevoegen en bewaren identiek is:

context.Blogs.Add(blog);
context.SaveChanges();

Read (selecteren)

Een enkele entiteit

In de praktische Xamarin uitwerking hebben we al meerdere selecties uitgevoerd, hieronder vindt u een overzicht en aanvulling.

Onderstaand voorbeeld laadt alle gegevens van de entiteit Blog met ToList().

using (var context = new BloggingContext())
{
    var blogs = context.Blogs.ToList();
}

Onderstaand voorbeeld laadt een specifieke Blog met Single(b => b.BlogId == 1)().

using (var context = new BloggingContext())
{
    var blog = context.Blogs
        .Single(b => b.BlogId == 1);
}

Onderstaand voorbeeld filtert de gegevens van de entiteit Blog met Contains().

using (var context = new BloggingContext())
{
    var blogs = context.Blogs
        .Where(b => b.Url.Contains("dotnet"))
        .ToList();
}

Onderstaand voorbeeld selecteert het laatste record en vraagt nadien de Id op.

using (var context = new BloggingContext())
{
    Blog BlogLaatsteRecord = context.Blogs.Last<Blog>();
    int Id = BlogLaatsteRecord.BlogId;
}

Sorteren

Sorteren kan gebeuren met LINQ via OrderBy en OrderByDescending.

Bijvoorbeeld om de Blog te sorteren op Url.

using (var context = new BloggingContext())
{
    Blog BlogGesorteerd = context.Blogs.OrderBy(b => b.Url)
}
using (var context = new BloggingContext())
{
    Blog BlogGesorteerd = context.Blogs.OrderByDescending(b => b.Url)
}

Wilt u gebruikmaken van de Sort-methode van een List dan wordt de code complexer:

using (var context = new BloggingContext())
{
    var blogs = context.Blogs.ToList();

    blogs.Sort(delegate (Blog x, Blog y)
    {
        return x.Url.CompareTo(y.Url);
    });
}

Indien de klasse een iComparer<T> geïmplementeerd heeft volstaat een simpele:

using (var context = new BloggingContext())
{
    var blogs = context.Blogs.ToList().Sort();
}

Maar dit is in ons voorbeeld niet het geval.

Gerelateerde entiteiten

Het is uiteraard ook mogelijk om gegevens uit meerdere, gerelateerde entiteiten te selecteren.

Onderstaand voorbeeld selecteert gegevens uit de entiteiten Blog en de gerelateerde entiteit Post met Include.

using (var context = new BloggingContext())
{
    var blogs = context.Blogs
        .Include(blog => blog.Posts)
        .ToList();
}

Onderstaand voorbeeld selecteert gegevens uit de entiteiten Blog en de gerelateerde entiteiten Post en Owner.

using (var context = new BloggingContext())
{
    var blogs = context.Blogs
        .Include(blog => blog.Posts)
        .Include(blog => blog.Owner)
        .ToList();
}

Onderstaand voorbeeld selecteert gegevens uit de entiteiten Blog en de gerelateerde entiteiten Post en de entiteit Author die gerelateerd is met Post.

using (var context = new BloggingContext())
{
    var blogs = context.Blogs
        .Include(blog => blog.Posts)
            .ThenInclude(post => post.Author)
        .ToList();
}

Verdere voorbeelden vindt u hier.

Bovenstaande voorbeelden hebben allen volgende beperkingen:

  • U selecteert altijd alle eigenschappen (kolommen).
  • Gerelateerde eigenschappen (kolommen) zijn niet rechtstreeks te binden met XAML

Om deze beperkingen niet te hebben verkies ik te werken met LINQ to Entities.

In onze praktisch Xamarin voorbeeld hebben we dit al eens gebruikt.

using (var context = new BloggingContext())
{
    from b in context.Blogs
    join p in context.Posts
        on b.BlogId equals p.BlogId
    where b.BlogId == BlogItem.BlogId
    orderby p.Title descending, p.Content
    select new
    {
        Naam = b.Name,
        Titel = p.Title,
        Inhoud = p.Content
    }
}

Dit heeft veel weg van een SQL-commando en zal, voor zij die SQL kennen, meteen duidelijk zijn. Let op, de select staat hier achteraan.


Update (wijzigen)

Een update is te vergelijken met een toevoeging. Het verschil bestaat erin dat bij een update de te wijzigen instantie (record) reeds bestaat en niet wordt toegevoegd.

In onderstaand voorbeeld wordt eerst de Blog gezocht, op basis van een variabele blogId, nadien wordt de nieuwe waarde toegekend en de databank bewaard.

 
using (var context = new BloggingContext()) 
{ 
    var blog = context.Blogs.Find(blogId);
    blog.Url = "http://sample.com/blog"; 
    context.SaveChanges(); 
} 

Onderstaande code zal voor ieder geselecteerde record de URL wijzigen.

using (var context = new BloggingContext())
{
    var blogs = context.Blogs.ToList();
    foreach (Blog B in blogs )
    {
        B.Url = "Test";
    }
}

Delete (verwijderen)

Om te verwijderen moet u, net als bij een update, eerst bepalen wat u wilt verwijderen, nadien volgt een eenvoudige Remove().

using (var context = new BloggingContext())
{
    var blog = context.Blogs.First();
    context.Blogs.Remove(blog);
    context.SaveChanges();
}

Hoe zit het met gerelateerde entiteiten, worden die ook verwijderd?

Wel, het hangt ervan af.

  • Is de relatie Required (de Foreign key kan niet null zijn) dan worden de gerelateerde instanties (records) eveneens verwijderd. Dit wordt een Cascade Delete genoemd.
  • Is de relatie Optional (de Foreign key kan null zijn) dan worden de Foreign keys van de gerelateerde instanties (records) op null gezet.

Wilt u hier alles over weten, lees dan hier verder.


Meerdere operaties en slechts één SaveChanges

Het is, uiteraard, mogelijk om meerdere operaties uit te voeren en pas, op het einde van alle operaties te bewaren.

Bekijk het onderstaand voorbeeld maar eens.

using (var context = new BloggingContext())
{
    // seeding database
    context.Blogs.Add(new Blog { Url = "http://sample.com/blog" });
    context.Blogs.Add(new Blog { Url = "http://sample.com/another_blog" });
    context.SaveChanges();
}

using (var context = new BloggingContext())
{
    // add
    context.Blogs.Add(new Blog { Url = "http://sample.com/blog_one" });
    context.Blogs.Add(new Blog { Url = "http://sample.com/blog_two" });

    // update
    var firstBlog = context.Blogs.First();
    firstBlog.Url = "";

    // remove
    var lastBlog = context.Blogs.Last();
    context.Blogs.Remove(lastBlog);

    context.SaveChanges();
}

Geef een reactie

Deze website gebruikt Akismet om spam te verminderen. Bekijk hoe je reactie-gegevens worden verwerkt.

  • Abonneer je op deze website d.m.v. e-mail

    Voer je e-mailadres in om je in te schrijven op deze website en e-mailmeldingen te ontvangen van nieuwe berichten.