Tuesday, March 15, 2016

Adding Artists to the Fan's List

I have made a method that can be included in the service to add artists the fan has selected to the fanArtist table.The code is commented to indicate what is going on.


 public int AddFanArtist( int fanKey, string artistName)
    {
        /*********************************
         * This method will add an artist to the artistFan
         * table. First we have to find the fan
         * and then the particular artist
         * Then we add the artist to the Fan's list
         * of artists to follow
         * **********************************/
        int result = 1;

        //get the fan. the key can come from their login
        Fan myFan = (from f in se.Fans
                     where f.FanKey == fanKey
                     select f).First();

        //get the artist by name
        Artist myArtist = (from a in se.Artists
                           where a.ArtistName.Equals(artistName)
                           select a).First();

        //add the artist to the fan;'s collection of artists
        myFan.Artists.Add(myArtist);

        //save the changes
        se.SaveChanges();

        return result;
    }
}

I also made a client method to show how you could use this. I used a CheckBoxList to select the artists from. Here is a picture of that on the web form

Obviously this could be made to look better. Here is the asp source code for the page


<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_Default" %>

<!DOCTYPE html>

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title></title>
</head>
<body>
    <form id="form1" runat="server">
    <div>
        <p>Select your artists and click enter to add them</p>
        <asp:CheckBoxList ID="CheckBoxList1" runat="server" RepeatColumns="3"></asp:CheckBoxList>
        <asp:Button ID="Button1" runat="server" Text="Add Artists" OnClick="Button1_Click" />
        <asp:Label ID="Label1" runat="server" Text="Label"></asp:Label>
    </div>
    </form>
</body>
</html>


Here is the code behind


using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;

public partial class _Default : System.Web.UI.Page
{
    ServiceReference1.FanArtistServiceClient sc = new ServiceReference1.FanArtistServiceClient();
    protected void Page_Load(object sender, EventArgs e)
    {
        //I hard coded the key in so I didn't have to do the login 
        //for this example
        Session["key"] = 2;
        if (!IsPostBack)
            PopulateArtists();
        
    }
    protected void Button1_Click(object sender, EventArgs e)
    {
        AddArtists();
    }

    protected void PopulateArtists()
    {
        //this method populates the CheckboxList
        //with artist names
        string[] artists = sc.GetArtist();
        CheckBoxList1.DataSource = artists;
        CheckBoxList1.DataBind();
    }

    protected void AddArtists()
    {
        //get the fan's key
        int key = (int)Session["key"];

        //loop through the checkboxList
        //to see what's checked
        foreach(ListItem i in CheckBoxList1.Items)
        {
            //if it is checked call the service method to add
            //it to the database
            if(i.Selected)
            {
                int x = sc.AddFanArtist(key, i.Text);
            }
        }
        Label1.Text = "Artist have been added";
        CheckBoxList1.Items.Clear();
    }
}

The next thing to do will be to make a query of all the artists and their shows for a particular fan. Here is my first take on that method. It works but could be made more elegant perhaps. This method also goes in the service.


 public List<ShowInfo> GetShowsForFanArtists(int fanKey)
    {
        //get the fan
        Fan myFan = (from f in se.Fans
                     where f.FanKey == fanKey
                     select f).First();

        List<ShowInfo> shows = new List<ShowInfo>();

        //this loop within a loop is very inefficient
         foreach(Artist a in myFan.Artists)
         {
             //get all the shows for the fan
             var shws = from s in se.Shows
                        from sd in s.ShowDetails
                        where sd.ArtistKey == a.ArtistKey
                        select new
                        {
                            s.ShowName,
                            s.ShowTime,
                            s.ShowDate,
                            s.ShowTicketInfo,
                            s.Venue.VenueName,
                            sd.Artist.ArtistName
                        };

             //loop through the shows and write them to 
             //ShowInfo objects then add those objects
             //to the list
             foreach(var sh in shws)
             {
                 ShowInfo info = new ShowInfo();
                 info.ShowName = sh.ShowName;
                 info.ShowDate = sh.ShowDate.ToString();
                 info.ShowTime = sh.ShowTime.ToString();
                 info.TicketInfo = sh.ShowTicketInfo;
                 info.VenueName = sh.VenueName;
                 info.ArtistName = sh.ArtistName;

                 shows.Add(info);
             }
             
             
         }
         return shows;
                  
    }

Thursday, March 10, 2016

XML in SQL Server

--xml
use CommunityAssist

--raw is the simplest way to take tabular data and turn it into XML
--below are variations of the raw
Select PersonLastName, PersonFirstName,
PersonUserName
 From Person
For xml raw

Select PersonLastName, PersonFirstName,
PersonUserName
 From Person
For xml raw, elements 

Select PersonLastName, PersonFirstName,
PersonUserName
 From Person
For xml raw, elements, root('people')



Select PersonLastName, PersonFirstName,
PersonUserName
 From Person
For xml raw('person'), elements, root('people')

--xml auto lets you create deeper Hierachies
--the query below groups all the grants of the same
--kind together
Select ServiceName, GrantKey, GrantNeedExplanation, GrantAmount
From CommunityService [Service]
inner Join ServiceGrant Grants
on [Service].ServiceKey = Grants.ServiceKey
order by Grants.ServiceKey
For XML auto, elements, root('root')

Select * From GrantReview

--this is a very simple example of XQuery, a language
--you can use to query XML documents
Select GrantReviewDate, GrantKey, 
GrantReviewNote.query('declare namespace mn="http://www.communityassist.org/reviewnotes"; 
//mn:reviewnote/mn:comment') as Attending
From GrantReview
Where GrantKey =40

--a schema collection stores an XML Schema.
--an xml schema is an xml document that describes
--the structure of another xml document
--a schema collection can be used to enforce the 
--structure of xml documents stored in the database
Create xml Schema Collection DonorNotesSchemaCollection
As
'<?xml version="1.0" encoding="utf-8"?>
<xs:schema attributeFormDefault="unqualified" elementFormDefault="qualified" targetNamespace="http://www.communityassist.org/donornote" xmlns:xs="http://www.w3.org/2001/XMLSchema">
  <xs:element name="donornote">
    <xs:complexType>
      <xs:sequence>
        <xs:element name="heading">
          <xs:complexType>
            <xs:sequence>
              <xs:element name="title" type="xs:string" />
            </xs:sequence>
          </xs:complexType>
        </xs:element>
        <xs:element name="body">
          <xs:complexType>
            <xs:sequence>
              <xs:element maxOccurs="unbounded" name="note" type="xs:string" />
            </xs:sequence>
          </xs:complexType>
        </xs:element>
      </xs:sequence>
    </xs:complexType>
  </xs:element>
</xs:schema>'

--creating a table with an xml column
--the xml columns is set to be validated by the schema
--in our schema collection. This insures that it has
--a consistent structure
Create table DonorReview
(
    DonorReviewKey int identity(1,1) primary key,
 DonationKey int foreign key references Donation(DonationKey),
 DonorReviewDate Date Default GetDate(),
 DonorNote xml(DonorNotesSchemaCollection)
)

Insert into DonorReview(DonationKey, DonorNote)
Values(4
, '<?xml version="1.0" encoding="utf-8"?>
<donornote xmlns="http://www.communityassist.org/donornote">
  <heading>
    <title>Big Donor</title>
  </heading>
  <body>
  <note>
    This donor just gave a huge donation
  </note>
  <note>
    We should spam them for more
  </note>
    </body>
</donornote>')

Select * from DonorReview

Tuesday, March 8, 2016

Administrative commands

--logins permissions
--authentication, authorization
--Create a sql Server login
Create login Alberts with password='Pass'

Use CommunityAssist
--add a user in communityAssist mapped to that login 
Create user Alberts for Login Alberts

--create a new role
Create Role EmployeeRole

--Grant permissions on objects to the role
Grant Select on CommunityService to EmployeeRole
Grant Select, Update on Person to EmployeeRole
Grant Select, Update, Insert on ServiceGrant to EmployeeRole
Grant Select on BusinessRules to EmployeeRole

--add the user to the role
exec sp_addrolemember 'EmployeeRole', 'Alberts'

--does exactly the same as the above
Alter role EmployeeRole Add member Alberts

Select * from sys.syslogins

use CommunityAssist
Select * from Person

--schema. A schema is a collection of related objects
go
--create a scheam
Create schema ClientSchema
Go
--add a view to the schema. Note the SchemaName.ObjectName
Create view ClientSchema.vw_Grants
As
Select GrantDate, GrantAmount, PersonKey,
GrantNeedExplanation
From ServiceGrant
go
Create view ClientSchema.Vw_Services
As
Select ServiceName, ServiceDescription, ServiceMaximum, ServiceLifetimeMaximum
From CommunityService
go
--create another role
Create role NewClientRole

--add permisions on the schema to the role
Grant Select on Schema::ClientSchema to NewClientRole

--new login
Create login Larry with password='Pass'
--new user with a default schema
Create user LarryUser for Login Larry with default_schema=ClientSchema
go
--Add user to role
Alter role NewClientRole Add member LarryUser

/*****************
backups and restores
*******************/
--a full backup
Backup Database CommunityAssist to disk ='C:\Backups\CommunityAssist.bak'
--a differential backup
Backup Database CommunityAssist to disk ='C:\Backups\CommunityAssist2.bak'
with Differential
--restore. Must restore the full then the differentials, then the log if backed up
use Master
Restore Database CommunityAssist from disk='C:\Backups\CommunityAssist.bak'
with norecovery
Restore Database CommunityAssist from Disk='C:\Backups\CommunityAssist2.bak'
with recovery

Monday, February 29, 2016

Security

Here are the somewhat fragmentary notes from our discussion on Security

Prevent Damage to Database
malicious attacks--
Accidents -- update table
Authentication--password username, windows

There are two basic kinds of Authentication

Windows, mapping windows user accounts to SQl Server
Sql Server Authentication-- a password and user name

2 step authentication, biometrics, voice, facial
Certificates Encryption

Authorization--What permissions do you have

Select read
Insert--write
update--write change
Delete remove data
execute run procedures
create--create database objects
Alter --modify database objects
Drop--remove database object

Actors--who is going use the database


Actor  Fan
Tables Select Insert Update Delete Notes
Venue   X   
Artist  X
Fan     x        x     x           Update own records
                                    only

Here is the code for creating a login, a user, a role, granting permissions to the role, and adding the user to the role

Grant create Table  to DonorRole 

Create Login George with password='Pass'
Use CommunityAssist
Create User George for login George

Create Role ClientRole

Grant select, insert on ServiceGrant to ClientRole
Grant Select on CommunityService to ClientRole

exec sp_addrolemember Clientrole, George


Thursday, February 25, 2016

triggers

--triggers
--stored procedure triggered by an event
--insert, update, delete
--for, after, instead of
-- for and after let the event happen and then
--execute the trigger code
--instead of intercepts the event and does
--the trigger code instead of the event
Create trigger tr_BigDonation on Donation
for insert 
As
if not exists
  (Select name from Sys.Tables
  Where name='BigDonations')
Begin
Create table BigDonations
(
 DonationKey int, 
 DonationDate DateTime, 
 DonationAmount money, 
 PersonKey int
)
End
Declare @DonationAmount money
Declare @Threshold money =500
Select @DonationAmount = DonationAmount
From Inserted
if @DonationAmount >= @Threshold
Begin
Insert into BigDonations(DonationKey,DonationDate,DonationAmount,
PersonKey)
Select DonationKey, DonationDate, DonationAmount,
PersonKey from Inserted
End

Select * from Person
Insert into Donation(DonationDate, DonationAmount, PersonKey)
Values(GetDate(), 550.75, 136)

Select * from Donation
Select * from BigDonations
Go
--Here is an alternate, more efficent version of that trigger
Create trigger tr_BigDonation on Donation
for insert 
As
--declare variables
Declare @DonationAmount money
Declare @Threshold money =500
--get value from temporary Inserted table
Select @DonationAmount = DonationAmount
From Inserted
--if the donation amount is 500 or above
if @DonationAmount >= @Threshold
Begin --outer if
if not exists
  (Select name from Sys.Tables
  Where name='BigDonations')
Begin--inner if
Create table BigDonations
(
 DonationKey int, 
 DonationDate DateTime, 
 DonationAmount money, 
 PersonKey int
)
End --end inner if
Insert into BigDonations(DonationKey,DonationDate,DonationAmount,
PersonKey)
Select DonationKey, DonationDate, DonationAmount,
PersonKey from Inserted
End --end outer if

go

Alter trigger tr_NoDelete on Donation
instead of Delete, update
As
  if not exists
     (Select name from Sys.Tables
      Where name='DeletedDonations')
   --if not create it
       Begin 
           Create table DeletedDonations
            (
           DonationKey int, 
           DonationDate DateTime, 
           DonationAmount money, 
           PersonKey int
             )    
       End
   Insert into DeletedDonations         (DonationKey,DonationDate, 
   DonationAmount, PersonKey)
 Select DonationKey, DonationDate, DonationAmount,
 PersonKey from Deleted



--
Delete from Donation where donationKey=47

Select * From Donation

Select * From DeletedDonations
go
--disable trigger to allow deletions
Disable trigger tr_NoDelete on Donation
go
--re enable trigger
enable Trigger tr_NoDelete on Donation

Tuesday, February 23, 2016

Stored Procedures

Use CommunityAssist
go
-- stored procedures
create proc usp_Donations
@PersonKey int
As
Select DonationKey, 
DonationDate, 
DonationAmount
From Donation
Where PersonKey = @PersonKey 

exec usp_Donations @PersonKey=3

Go
--add new person
--Get all the parameters for Person,
--personAddress and PersonContact
--Make sure the person is not in the database
--already
--begin a transaction
--Begin a try--
--hash their password
--insert into person
--insert into personAddress --getting the person key
--insert into personContact with key
--commit tran
--or catch the errors and rollaback

Version 1

Create proc usp_AddPerson
@PersonLastName nvarchar(255), 
@PersonFirstName nvarchar(255), 
@PersonUsername nvarchar(25), 
@PersonPlainPassword nvarchar(50), 
@Street nvarchar(255), 
@Apartment nvarchar(255) = null, 
@State nvarchar(2) = 'WA', 
@City nvarchar(255) = 'Seattle', 
@Zip nvarchar(10), 
@HomePhone nvarchar(255) = null,
@WorkPhone nvarchar(255)=null
As
Declare @Passkey int =dbo.fx_Seed()
Declare @HomePhoneType int =1
Declare @WorkPhoneType int =2
Insert into Person
(PersonLastName, PersonFirstName, PersonUsername, PersonPlainPassword, 
Personpasskey, PersonEntryDate, PersonUserPassword)
Values(@PersonLastName, @PersonFirstName,
@PersonUsername, @PersonPlainPassword,
@Passkey, GetDate(),dbo.fx_hashPass(@PassKey, @PersonPlainPassword))
Declare @PersonKey int = Ident_Current('Person')
Insert into PersonAddress(Street, Apartment, State, City, Zip, PersonKey)
Values (@Street, @Apartment,@State, @City,@Zip, @PersonKey)
Insert into PersonContact(PersonKey, ContactInfo, ContactTypeKey)
Values(@PersonKey, @HomePhone, @HomePhoneType)
Insert into PersonContact(PersonKey, ContactInfo, ContactTypeKey)
Values(@PersonKey, @WorkPhone, @WorkPhoneType)

exec Usp_AddPerson
@PersonLastName='Anderson', 
@PersonFirstName='Marty', 
@PersonUsername='MAnderson@gmail.com', 
@PersonPlainPassword='martyPass', 
@Street='1002 South Somewhere', 
 @Zip='98100', 
 @HomePhone='2065559873', 
 @WorkPhone='2065558769'

Version 2

 Go
 Alter proc usp_AddPerson
@PersonLastName nvarchar(255), 
@PersonFirstName nvarchar(255), 
@PersonUsername nvarchar(25), 
@PersonPlainPassword nvarchar(50), 
@Street nvarchar(255), 
@Apartment nvarchar(255) = null, 
@State nvarchar(2) = 'WA', 
@City nvarchar(255) = 'Seattle', 
@Zip nvarchar(10), 
@HomePhone nvarchar(255) = null,
@WorkPhone nvarchar(255)=null
As
--Declare variables
Declare @Passkey int =dbo.fx_Seed()
Declare @HomePhoneType int =6
Declare @WorkPhoneType int =2
Begin Tran --start transaction
Begin try--start Try
--insert into Person
Insert into Person
(PersonLastName, PersonFirstName, PersonUsername, PersonPlainPassword, 
Personpasskey, PersonEntryDate, PersonUserPassword)
Values(@PersonLastName, @PersonFirstName,
@PersonUsername, @PersonPlainPassword,
@Passkey, GetDate(),dbo.fx_hashPass(@PassKey, @PersonPlainPassword))
--get person key
Declare @PersonKey int = Ident_Current('Person')
--insert int personAddress
Insert into PersonAddress(Street, Apartment, State, City, Zip, PersonKey)
Values (@Street, @Apartment,@State, @City,@Zip, @PersonKey)
--insert home phone
Insert into PersonContact(PersonKey, ContactInfo, ContactTypeKey)
Values(@PersonKey, @HomePhone, @HomePhoneType)
--insert work phone
Insert into PersonContact(PersonKey, ContactInfo, ContactTypeKey)
Values(@PersonKey, @WorkPhone, @WorkPhoneType)
commit tran --all is good write it
End try
Begin catch --if an error will fall here
Rollback Tran--undo the transaction
print 'Transaction rolled back'
print Error_Message();
End Catch

exec Usp_AddPerson
@PersonLastName='Munse', 
@PersonFirstName='Nelson', 
@PersonUsername='NMunse@gmail.com', 
@PersonPlainPassword='MunsePass', 
@Street='1004 North Somewhere', 
 @Zip='98100', 
 @HomePhone='2065559773', 
 @WorkPhone='2065558729'

Third Version

  Alter proc usp_AddPerson
@PersonLastName nvarchar(255), 
@PersonFirstName nvarchar(255), 
@PersonUsername nvarchar(25), 
@PersonPlainPassword nvarchar(50), 
@Street nvarchar(255), 
@Apartment nvarchar(255) = null, 
@State nvarchar(2) = 'WA', 
@City nvarchar(255) = 'Seattle', 
@Zip nvarchar(10), 
@HomePhone nvarchar(255) = null,
@WorkPhone nvarchar(255)=null
As
--Declare variables
Declare @Passkey int =dbo.fx_Seed()
Declare @HomePhoneType int =1
Declare @WorkPhoneType int =2
if exists
 (Select PersonKey from Person
 Where PersonLastName =@PersonLastName
 And PersonFirstname=@PersonFirstName
 And PersonUserName=@PersonUsername)
Begin --begin if
Print 'Person already exists'
end --end if
Else
Begin--begin else
Begin Tran --start transaction
Begin try--start Try
--insert into Person
Insert into Person
(PersonLastName, PersonFirstName, PersonUsername, 
PersonPlainPassword, 
Personpasskey, PersonEntryDate, PersonUserPassword)
Values(@PersonLastName, @PersonFirstName,
@PersonUsername, @PersonPlainPassword,
@Passkey, GetDate(),dbo.fx_hashPass(@PassKey, @PersonPlainPassword))
--get person key
Declare @PersonKey int = Ident_Current('Person')
--insert int personAddress
Insert into PersonAddress(Street, Apartment, State, City, Zip, PersonKey)
Values (@Street, @Apartment,@State, @City,@Zip, @PersonKey)
--insert home phone
Insert into PersonContact(PersonKey, ContactInfo, ContactTypeKey)
Values(@PersonKey, @HomePhone, @HomePhoneType)
--insert work phone
Insert into PersonContact(PersonKey, ContactInfo, ContactTypeKey)
Values(@PersonKey, @WorkPhone, @WorkPhoneType)
commit tran --all is good write it
End try
Begin catch --if an error will fall here
Rollback Tran--undo the transaction
print 'Transaction rolled back'
print Error_Message();
End Catch
end --end else

exec Usp_AddPerson
@PersonLastName='Munse', 
@PersonFirstName='Nelson', 
@PersonUsername='NMunse@gmail.com', 
@PersonPlainPassword='MunsePass', 
@Street='1004 North Somewhere', 
 @Zip='98100', 
 @HomePhone='2065559773', 
 @WorkPhone='2065558729'

Monday, February 22, 2016

ERD Individual Assignment 2 Diagrams

Recipe Ingredient Entities


Student Course Entities


Dentist office Entities