further exploring database operations from c#/.net jim warren, [email protected] compsci 280 s2...

16
Further exploring database operations from C#/.NET Jim Warren, [email protected] COMPSCI 280 S2 2015 Enterprise Software Development

Upload: derrick-neal

Post on 31-Dec-2015

219 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: Further exploring database operations from C#/.NET Jim Warren, jim@cs.auckland.ac.nz COMPSCI 280 S2 2015 Enterprise Software Development

Further exploring database operations from C#/.NETJim Warren, [email protected]

COMPSCI 280 S2 2015Enterprise Software Development

Page 2: Further exploring database operations from C#/.NET Jim Warren, jim@cs.auckland.ac.nz COMPSCI 280 S2 2015 Enterprise Software Development

Today’s learning objectives To be able to use the LINQ (language-integrate

query) approach for database queries in C#/.NET To be able to update the database from C#/.NET

To conceptualise an application in terms of CRUD (create, read, update, delete) operations

To consider the state of an object instance in relation to the database context

COMPSCI 2802

Page 3: Further exploring database operations from C#/.NET Jim Warren, jim@cs.auckland.ac.nz COMPSCI 280 S2 2015 Enterprise Software Development

Last lecture… We learned to connect to a database, set up a

model of its tables and create queries like:

This is OK, but it has some disadvantages We don’t get support from the IDE for the query itself

It’s an arbitrary string – no type checking, no intellisense It’s a bit of a pain to always need to figure out the

type of the returned instances It’s also a potential security hole…

COMPSCI 2803

var x2 = db.Database.SqlQuery<Employee>("select * from employee");

Page 4: Further exploring database operations from C#/.NET Jim Warren, jim@cs.auckland.ac.nz COMPSCI 280 S2 2015 Enterprise Software Development

SQL injection

COMPSCI 2804

Page 5: Further exploring database operations from C#/.NET Jim Warren, jim@cs.auckland.ac.nz COMPSCI 280 S2 2015 Enterprise Software Development

The LINQ approach Makes the query actually a statement in the C#

language

SQL’s select-from-where is turned on its head a bit Makes the intellisense work better to use from-where-select order

In this case the return value is a collection of objects of a class we’ve already defined in our Model Because we had said: public DbSet<Employee> Employees { get; set; }

and had defined the Employee class with property names exactly aligned to the columns of the DBMS table

COMPSCI 2805

using (EmployeesContext db = new EmployeesContext()) {

var emps = from e in db.Employees where e.DateOfBirth.Year < 1975 select e;

string surname1=emps.First().surname } We get access to

all C#’s operators, too!

Page 6: Further exploring database operations from C#/.NET Jim Warren, jim@cs.auckland.ac.nz COMPSCI 280 S2 2015 Enterprise Software Development

LINQ Join We could, of course, have sent join queries to MySQL as a

string, but LINQ brings Join into C#

Notice the ‘select’ Even if we included in the model definitions of the ‘categories’ and

‘products’ tables, we’d need a new class to hold the combination of a product name and a category name

The ‘new’ statement is constructing an anonymous type with properties ProductName and Category

innerJoinQuery will be implicitly typed to a generic collection of instances with the generic’s type parameter being this new 2-property anonymous type We can still do a foreach statement on innerJoinQuery to loop through the

results COMPSCI 2806

var innerJoinQuery = from category in db.categories join prod in db.products on category.ID equals prod.CategoryID select new { ProductName = prod.Name, Category = category.Name };

Notice we said ‘equals’ as a keyword (not the = sign); this gives system most flexibility to exploit indices or other

optimise the join

Page 7: Further exploring database operations from C#/.NET Jim Warren, jim@cs.auckland.ac.nz COMPSCI 280 S2 2015 Enterprise Software Development

More LINQ – group by Get a count of how many employees with each

surname

Use ‘group’… ‘by’ keyword pair Note use of ‘into’ and naming a second index variable

(‘g’ in this case) Note the special property Key is the thing we grouped

by

COMPSCI 2807

var cnts = from emp in db.Employees group emp by emp.Surname into g select new {s=g.Key, cnt=g.Count()};foreach (var c in cnts) Console.WriteLine("Key: " + c.s + " Count: " + c.cnt);

Page 8: Further exploring database operations from C#/.NET Jim Warren, jim@cs.auckland.ac.nz COMPSCI 280 S2 2015 Enterprise Software Development

Or method based GroupBy Use GroupBy method allowing a lambda to

specify just what we want the grouping Key to be

And you can apply one method onto the result of another

COMPSCI 2808

foreach (var c in db.Employees.GroupBy(a=>a.Surname.Substring(0,1))) Console.WriteLine("Key2: " + c.Key+ " Count2: " + c.Count());

foreach (var c in db.Employees.GroupBy(a => Math.Floor(a.DateOfBirth.Year/10f))) Console.WriteLine("Key2: " + c.Key + "0's Count2: " + c.Count());

foreach (var c in db.Employees.Where(a=>a.Surname.CompareTo("F")>=0).GroupBy(a=>a.Surname.Substring(0,1))) Console.WriteLine("Key2: " + c.Key+ " Count2: " + c.Count());

Count of employees by first letter of surname

Count of employees by decade of birth

Page 9: Further exploring database operations from C#/.NET Jim Warren, jim@cs.auckland.ac.nz COMPSCI 280 S2 2015 Enterprise Software Development

What about the rest of the CRUD?! CRUD: Create, Read, Update, Delete A CRUD matrix can be a useful specification for the

scope of programming tasks E.g. to describe the ‘life cycle’ of each entity in a

system; e.g. a hotel reservation On some screen (e.g. ‘booking’) it is created (SQL INSERT, not

CREATE like making a new table) There may be a screen to UPDATE it (e.g. ‘change booking’)

which probably also reads the current value (‘R’ of CRUD, SQL SELECT)

And there will be one or more ways to DELETE it (e.g. from a cancellation action on the change booking screen or a dedicated cancellation screen, and also once the person has checked in) – then again, you might not actually delete in a SQL sense, but UPDATE it to cancelled or utilised status

COMPSCI 2809

Page 10: Further exploring database operations from C#/.NET Jim Warren, jim@cs.auckland.ac.nz COMPSCI 280 S2 2015 Enterprise Software Development

CRUD matrix (well, for one entity)Program (or ‘screen’) Entity=reservation

Make reservation C

Check reservation R

Review/change reservation RU

Review/cancel reservation RD*

Client arrives (takes up reserved room)

D**

COMPSCI 28010

For a more involved system you may have many entities represented as further columns Each cell marked with a subset of the letters in

‘CRUD’

* Or update status to cancelled** Or update status to taken

Page 11: Further exploring database operations from C#/.NET Jim Warren, jim@cs.auckland.ac.nz COMPSCI 280 S2 2015 Enterprise Software Development

The UPDATE Native SQL version

Given that I have a reference to an object emp of class Employee with updated values:

COMPSCI 28011

using (EmployeesContext db = new EmployeesContext()) { string sql=String.Format( "UPDATE employee SET Surname='{0}',GivenNames='{1}',"+ "DateOfBirth='{2:yyyy-MM-dd}' WHERE id={3}", emp.Surname,emp.GivenNames,emp.DateOfBirth,emp.id);

db.Database.ExecuteSqlCommand(sql);...}

Here we’re just building the text of a SQL command with the help of String.Format to plug in the parameters from our C# code at the curly braces (note the 3rd parameter - #2 counting from 0! – is formatted so MySQL recognises the date literal; also note carefully the double quotes interpreted by C# and the signle quotes that are for MySQL

Then we just .ExecuteSqlCommand (as compared to doing . SqlQuery) on the database context to tell MySQL to have at it

Re-establish the database connection

Page 12: Further exploring database operations from C#/.NET Jim Warren, jim@cs.auckland.ac.nz COMPSCI 280 S2 2015 Enterprise Software Development

Native INSERT Similar to the UPDATE, once we have a database

context established we can do INSERT (or DELETE) SQL

COMPSCI 28012

string sql_ins = String.Format("INSERT INTO employee (GivenNames,SurName,DateOfBirth) "+ "VALUES ('{0}','{1}','{2:yyyy-MM-dd}')","Bob", "Barker",DateTime.Now);db.Database.ExecuteSqlCommand(sql_ins);

string sql_del = "delete from employee where GivenNames='Bob'";db.Database.ExecuteSqlCommand(sql_del);

Page 13: Further exploring database operations from C#/.NET Jim Warren, jim@cs.auckland.ac.nz COMPSCI 280 S2 2015 Enterprise Software Development

The UPDATE v2 Entity Framework version

If you’ve gotten an object from the database, the system tracks that that object is “attached” to the database context

If you want to update a record Retrieve it Change properties of the object as you wish Save the changes

COMPSCI 28013

using (EmployeesContext db = new EmployeesContext()){ var updEmp = from emp in db.Employees where emp.Surname == "Barker" select emp; foreach (Employee e3 in updEmp) e3.Surname = "Good"; db.SaveChanges();...}

Every employee with surname ‘Barker’ gets updated to surname ‘Good’

Page 14: Further exploring database operations from C#/.NET Jim Warren, jim@cs.auckland.ac.nz COMPSCI 280 S2 2015 Enterprise Software Development

INSERT by adding If you simply create a ‘new’ object of the class of

a record, it isn’t attached to the database context by default However, you use the appropriate DbSet’s Add

method to attach it Use the database context’s SaveChanges method to

make the insertion stick

COMPSCI 28014

using (EmployeesContext db = new EmployeesContext()) {...

var e1 = new Employee{GivenNames="Tommy", Surname="Tank"}; db.Employees.Add(e1); db.SaveChanges();

Adds a new employee with name “Tommy Tank”, letting the ‘id’ be supplied automatically and leaving DateOfBirth unspecified (probably will be set to 1 Jan 1 AD !)

Note curly-brace “object initializer” syntax. Invokes constructor and then assigns the specified values to the named properties of the new object

Page 15: Further exploring database operations from C#/.NET Jim Warren, jim@cs.auckland.ac.nz COMPSCI 280 S2 2015 Enterprise Software Development

Delete To delete

Get a handle on the relevant object(s) (e.g. with a query, like we did for update)

Invoke the Remove method of the DbSet with the object to delete as a parameter

Note: if deleting (or in some cases updating) where there are foreign key constraints you may need to think carefully about the ‘cascade’ of effects with respect to referential integrity (see https://technet.microsoft.com/en-us/library/aa902684(v=sql.80).aspx)

COMPSCI 28015

using (EmployeesContext db = new EmployeesContext()) {...

var deletedEmp = from emp in db.Employees where emp.Surname == "Tank" select emp; foreach (Employee emp in deletedEmp) db.Employees.Remove(emp); db.SaveChanges();

Page 16: Further exploring database operations from C#/.NET Jim Warren, jim@cs.auckland.ac.nz COMPSCI 280 S2 2015 Enterprise Software Development

Where we’re up to We’ve learned some basics of .NET and C# We’ve seen that we can interact with our DBMS

by sending it native SQL or using C#/.NET language-embedded syntax (LINQ and Entity Framework)

Now… Work the second labsheet (if you haven’t already) Get seriously into Assignment 2 See you other side of the break!

FYI, I’m on leave first week of the break, but will be at work and answering questions second week of the break

COMPSCI 28016