ASP.Net's andmete kasutamine LINQ abil

From EIK wiki

Järgnev jutt on jällegi pärit "Andmebaasipõhiste veebirakenduste arendamine Microsoft Visual Studio 2008 ja SQL Server 2008 baasil" õppematerjalist (lk 457-464)

Andmete kasutamine LINQ abil

Andmete leidmiseks LINQ abil tuleb esmalt luua App_Code kausta „LINQ to SQL“ klass, mis hakkab korraldama andmevahetust veebirakenduse ja andmebaasi vahel.

LINQ to SQL Classes lisamine

Selleks lisage oma veebi App_Code kausta uus item, mis on „LINQ to SQL Classes“ tüüpi.

  • Avaneb LINQ to SQL klassi disainerivaade, kus saate lohistada kõik teile olulised tabelid, koos nendevaheliste seostega LINQ to SQL klassi. Näiteks haarame ServerExplorerist oma andmebaasis paikneva toodete tabeli ning lohistame disainerisse:
    • Vajadusel saate lohistada sellele skeemile tabeleid juurde ning määrata keerukamaid meetodeid nii andmete leidmiseks kui muutmiseks. Samas kui teile piisab sellisest lihtsustatud ligipääsust siis võite selle klassi ära salvestada ja hakata teda kasutama andmetega manipuleerimisel.
    • Selles disainerivaates näete te selle klassi graafilist kuju. Klassi tegelik kood paikneb selle disainifaili taba olevas koodifailis <klassinimi>.designer.cs
    • Lisaks on seal ka fail <klassinimi>.dbml.layout, milles on XML kujul see sama graafiline vaade teie loodud klassile.

Visates kiire pilgu loodud koodile võib selles välja lugeda, et tegemist on maskeeringuga, kus klass Toode maskeerib ära andebaasis oleva tabeli Toode, koos kõigi selle tabeli omaduste ja muutmisvõimalustega ning klass ToodeDataContext on andmeallikas LINQ päringute tegemiseks, mis kasutab seda maskeeritud Toode tabelit.

#pragma warning disable 1591
//-------------------------------------------------------------------------
// <auto-generated>
//     This code was generated by a tool.
//     Runtime Version:2.0.50727.1433
//
//     Changes to this file may cause incorrect behavior and will be lost 
//     if the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Data.Linq;
using System.Data.Linq.Mapping;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;

[System.Data.Linq.Mapping.DatabaseAttribute(Name="pood")]
public partial class ToodeDataContext : System.Data.Linq.DataContext
{
	
	private static System.Data.Linq.Mapping.MappingSource mappingSource = new AttributeMappingSource();
	
  #region Extensibility Method Definitions
  partial void OnCreated();
  partial void InsertToode(Toode instance);
  partial void UpdateToode(Toode instance);
  partial void DeleteToode(Toode instance);
  #endregion
	
	public ToodeDataContext() : 
			base(global::System.Configuration.ConfigurationManager.ConnectionStrings["poodConnectionString"].ConnectionString, mappingSource)
	{
		OnCreated();
	}
	
	public ToodeDataContext(string connection) : 
			base(connection, mappingSource)
	{
		OnCreated();
	}
	
	public ToodeDataContext(System.Data.IDbConnection connection) : 
			base(connection, mappingSource)
	{
		OnCreated();
	}
	
	public ToodeDataContext(string connection, System.Data.Linq.Mapping.MappingSource mappingSource) : 
			base(connection, mappingSource)
	{
		OnCreated();
	}
	
	public ToodeDataContext(System.Data.IDbConnection connection, System.Data.Linq.Mapping.MappingSource mappingSource) : 
			base(connection, mappingSource)
	{
		OnCreated();
	}
	
	public System.Data.Linq.Table<Toode> Toodes
	{
		get
		{
			return this.GetTable<Toode>();
		}
	}
}

[Table(Name="dbo.Toode")]
public partial class Toode : INotifyPropertyChanging, INotifyPropertyChanged
{
	
	private static PropertyChangingEventArgs emptyChangingEventArgs = new PropertyChangingEventArgs(String.Empty);
	
	private int _ToodeID;
	
	private string _Nimetus;
	
	private int _KogusLaos;
	
	private System.Data.Linq.Binary _Pilt;
	
    #region Extensibility Method Definitions
    partial void OnLoaded();
    partial void OnValidate(System.Data.Linq.ChangeAction action);
    partial void OnCreated();
    partial void OnToodeIDChanging(int value);
    partial void OnToodeIDChanged();
    partial void OnNimetusChanging(string value);
    partial void OnNimetusChanged();
    partial void OnKogusLaosChanging(int value);
    partial void OnKogusLaosChanged();
    partial void OnPiltChanging(System.Data.Linq.Binary value);
    partial void OnPiltChanged();
    #endregion
	
	public Toode()
	{
		OnCreated();
	}
	
	[Column(Storage="_ToodeID", AutoSync=AutoSync.OnInsert, DbType="Int NOT NULL IDENTITY", IsPrimaryKey=true, IsDbGenerated=true)]
	public int ToodeID
	{
		get
		{
			return this._ToodeID;
		}
		set
		{
			if ((this._ToodeID != value))
			{
				this.OnToodeIDChanging(value);
				this.SendPropertyChanging();
				this._ToodeID = value;
				this.SendPropertyChanged("ToodeID");
				this.OnToodeIDChanged();
			}
		}
	}
	
	[Column(Storage="_Nimetus", DbType="NVarChar(50) NOT NULL", CanBeNull=false)]
	public string Nimetus
	{
		get
		{
			return this._Nimetus;
		}
		set
		{
			if ((this._Nimetus != value))
			{
				this.OnNimetusChanging(value);
				this.SendPropertyChanging();
				this._Nimetus = value;
				this.SendPropertyChanged("Nimetus");
				this.OnNimetusChanged();
			}
		}
	}
	
	[Column(Storage="_KogusLaos", DbType="Int NOT NULL")]
	public int KogusLaos
	{
		get
		{
			return this._KogusLaos;
		}
		set
		{
			if ((this._KogusLaos != value))
			{
				this.OnKogusLaosChanging(value);
				this.SendPropertyChanging();
				this._KogusLaos = value;
				this.SendPropertyChanged("KogusLaos");
				this.OnKogusLaosChanged();
			}
		}
	}
	
	[Column(Storage="_Pilt", DbType="VarBinary(MAX)", UpdateCheck=UpdateCheck.Never)]
	public System.Data.Linq.Binary Pilt
	{
		get
		{
			return this._Pilt;
		}
		set
		{
			if ((this._Pilt != value))
			{
				this.OnPiltChanging(value);
				this.SendPropertyChanging();
				this._Pilt = value;
				this.SendPropertyChanged("Pilt");
				this.OnPiltChanged();
			}
		}
	}
	
	public event PropertyChangingEventHandler PropertyChanging;
	
	public event PropertyChangedEventHandler PropertyChanged;
	
	protected virtual void SendPropertyChanging()
	{
		if ((this.PropertyChanging != null))
		{
			this.PropertyChanging(this, emptyChangingEventArgs);
		}
	}
	
	protected virtual void SendPropertyChanged(String propertyName)
	{
		if ((this.PropertyChanged != null))
		{
			this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
		}
	}
}
#pragma warning restore 1591

LinqDatasource kasutamine

Loodud klassi kasutamiseks andmeallikana tuleb lisada veebilehele LinqDatasource. Lohistades vastava elemendi Toolbox’ilt oma veebilehele, ning seadistades teda läbi seadistusvõluri, mis paikneb Configure Data Source käsu all.

Kui peale seda protsessi vaatate oma veebilehe koodi siis leiate, et tulemuseks element asp:LinqDataSource, mis seab ContextTypeName atribuudi abil kokku loodud andmeallika ning LINQ to SQL klassi:

<asp:LinqDataSource ID="LinqDataSource1" runat="server" 
     ContextTypeName="ToodeDataContext" TableName="Toodes">
</asp:LinqDataSource>
Andmeallik kasutamiseks GridView peal tuleb vaid viidata loodud andmeallikale:
<asp:GridView ID="GridView1" runat="server" 
              AutoGenerateColumns="True" 
              DataKeyNames="ToodeID" 
              DataSourceID="LinqDataSource1" />

Kokkuvõtteks võiks öelda, et LINQ kasutamine vajab esmalt pisut rohkem ettevalmistust, kui traditsiooniline ADO.NET, kuid kui ettevalmistused tehtud (LINQ to SQL klassi loomise teel) on selle kasutamine oluliselt lihtsam kui seda on ADO.NET kasutamine. Lisaks sellele on loodud ToodeDataContext kasutatav ka programmelt e. C# koodi abil. See võimaldab teil luua nt programme, mis vaatavad selle toodete tabeli rea kaupa üle ning teevad vastavalt vajadusele seal muudatusi jne.

Samuti on hiljem selgub, et andmete poole pöördumist või nendega manipuleerimist on vaja täiustada siis saate seda teha ühes keskses kohas (LINQ to SQL klassis) ning tehtud muudatustega arvestatakse kõigil veebilehtedel, mis neid andmeid kasutasid. Kasutades traditsioonilist ADO.NET lähenemist peate te muudatusi tegema eraldi igal lehel, mis andmetega tegeleb!