Presentation - Spring.NET

basiliskcanoeSoftware and s/w Development

Nov 2, 2013 (3 years and 9 months ago)

106 views

Welcome to

Introduction to Data Access with
Spring.NET

Mark Pollack

Principal

CodeStreet LLC

Overall Presentation Goal

Learn about Spring.NET's support for
ADO.NET, O/R Mappers, and
transaction management abstraction


Speaker’s Qualifications

Mark Pollack is a founding partner at CodeStreet
LLC, a software and consulting firm in the
financial services industry.

.NET and J2EE architect and developer
specializing in front office solutions, EAI, and
message based middleware

Spring Developer (2003)


JmsTemplate

Founder of Spring.NET (2004)

Co
-
lead of Spring.NET with Aleks Seovic

Outline

Quick overview of Spring.NET

.NET Data Access Landscape

ADO.NET Framework

NHibernate integration

Transaction management

Spring.NET Overview

Concepts in Spring are not platform specific

Want to build .NET apps in a similar way


Need for an application framework

Not a blind port of Spring

Version 1.0 released September 2005

Spring.NET subsystems

Core

AOP

Services

(Exporters)

Data Access

Web

Desktop

3
rd

Party
Integration

Data Access Landscape

Wide range of data access strategies and technologies

Developer toolbox has matured


PEAA


Fowler


Know how to ‘codify’ best practice patterns

Technologies


ADO.NET, O/R Mappers

Transaction Management


Local


ADO.NET


System.Transactions
(.NET 2.0)


Distributed
-

MS
-
DTC/COM+Services


EnterpriseServices
(.NET 1.1)


System.Transactions
(.NET 2.0)


.NET 3.0 (WinFX)

Spring Data Access

Provide uniform best practice approach across
data access technologies.

IoC integration

Transaction management


Programmatic and declarative

Resource management


‘Template’/callback APIs

Exception Translation

Added value


Make ‘native’ APIs easier to use


ADO.NET


Higher level encapsulation of Data Access


DAO support classes, “AdoOperation” objects

Spring.NET Data Access

“Spring.Java” users should feel right at home


ADO.NET, to first order


Java ported O/R Mappers, to second order.

ADO.NET framework

NHibernate support


iBatis.NET under development.

Early Adopter stage


Well hedged by “Spring.Java” design


A small feature set used in production now.


Daily P/L calculations and reporting for a major hedge fund.

ADO.NET API overview

Uniform API between “Text SQL” and Stored procedures


IDbCommand property: CommandType

IDbParameters used extensively


In, Out, InOut, Return

Few easy methods on Command class


ExecuteScalar, ExecuteNonQuery, ExecuteReader


DataSets


DataAdapter + CRUD IDbCommands

Parameter binding


By name is prevalent in API


Generally, no fallback to generic placeholder if provider supports
named parameters

Transaction object


Can assign to a command object.

Motivations for ADO.NET framework

Provide usable provider independent API


No factory in BCL
(.NET 1.1)


Simplistic and at times incomplete interfaces

IoC integration


Connection String management

Easier parameter management


BCL interfaces leads to verbose code

Exception Handling


Not singly rooted
(.NET 1.1)


Base exception + error code
(.NET 2.0)


No portable “DAO” exception hierarchy

Motivations for ADO.NET framework II

Centralize resource management


Connection, Command, DataReader


‘using’ is A Good Thing.


Does reduce try/finally verbosity but ‘no catch’

Transaction management


Ad
-
hoc passing around of Transaction object

API Quirks


Exception reading a null from IDataReader

AdoTemplate

Execute()


ICommandCallback, CommandDelegate


Use of delegates


i.e. stateless callbacks.


Use of variable length arguments, boxing

ExecuteScalar(), ExecuteNonQuery(), Query()


IRowCallback, IRowMapper, IResultSetExtractor

Variations with


IDbCommandSetter, IDbCommandCreator


One “inline” parameter


string name, Enum dbType, int size, object parameterValue

Factory Method for creating IDbParameters

Callback Interface

Central method of AdoTemplate


Resource Management


Transaction Aware

public interface IAdoOperations {


. . .


public Object Execute(ICommandCallback action)
;



public Object Execute(CommandDelegate del)
;

}


public interface ICommandCallback {


Object DoInCommand(IDbCommand command);

}


public
delegate Object CommandDelegate(IDbCommand command);

Standard ADO.NET

public class NativeAdoTestObjectDao : ITestObjectDao {



// Connection String Property ...



public void Create(string name, int age) {


using (SqlConnection connection =



new SqlConnection(connectionString)) {





string sql =


String.Format("insert into TestObjects(Age, Name) " +



"VALUES ({0}, '{1}')", age, name);



using (SqlCommand cmd = new SqlCommand(sql, connection) {


connection.Open();


comm.ExecuteNonQuery();


}


}


}

}

AdoTemplate Example

public class TestObjectDao :
AdoDaoSupport
,


ITestObjectDao {



public void Create(string name, int age) {



AdoTemplate.ExecuteNonQuery
(


String.Format(CommandType.Text,




"insert into TestObjects(Age, Name) "



+ "VALUES ({0}, '{1}')", age, name));


}

}

<object id="testObjectDao"


type=“MyApp.DAL.TestObjectDao,MyApp.DAL">


<property name="ConnectionString"


value="Data Source=(local);Database=Spring;




UserID=springqa;Password=springqa;




Trusted_Connection=False"/>

</object>

Connection String Management

Custom Schema to set common
connection string properties


XML’ized .NET 2.0 Connection String builders

<sqlServerConnection name="myConnectionString"




dataSource="(local)"


initialCatalog="Northwind"


persistSecurityInfo="true"


userID=“${userID}"


password="${password}"



/>

Parameter Creation

Use any provider Sql Type Enumeration

Helper methods for parameter creation


AddOut, AddInOut, DataSet related

IDbParameters parameters = adoTemplate.NewDbParameters();


parameters.Add("Name", DbType.String, 12).Value = name;

parameters.Add("Age",
SqlDbType.Int
).Value = age;


adoTemplate.ExecuteNonQuery(CommandType.Text, sql,






parameters);

AdoOperations

OO model for DB operations


Preferred approach

AdoQuery

-

Result set mapping to objects

AdoNonQuery
-

Insert/Update/Delete

AdoScalar


Return single value

StoredProcedure


out parameters and multiple result sets

AdoDataSetQuery*



Return DataSet

Use of
ICommandCreater

implementation for
efficient parameter re
-
creation.

public class TestObjectQuery : MappingAdoQuery {



private static string sql =


"select TestObjectNo, Age, Name from TestObjects";




public TestObjectQuery(IDbProvider dbProvider)


: base(dbProvider, sql) {


CommandType = CommandType.Text;


}



protected override object MapRow(
IDataReader

reader,







int num) {


TestObject to = new TestObject();


to.ObjectNumber = reader.GetInt32(0);


to.Age = reader.GetInt32(1);


to.Name = reader.GetString(2);


return to;


}

}

MappingAdoQuery

NullMappingDataReader

NullMappingDataReader

IDataReaderWrapper


NullMappingDataReader implementation


Specified in AdoTemplate


Say goodbye to code like this…

to.ObjectNumber = (!reader.IsDBNull(0)) ? reader.GetInt32(0) :
-
1;

to.Age = (!reader.IsDBNull(1)) ? reader.GetInt32(1) :
-
1;

to.Name = (!reader.IsDBNull(2)) ? reader.GetString(2) : String.Empty;




TestObjectQuery testObjectQuery =


new TestObjectQuery(dbProvider);

IList testObjectList =


testObjectQuery.Query();




AdoNonQuery

public class CreateTestObjectNonQuery : AdoNonQuery {



private static string sql =


"insert into TestObjects(Age,Name) values (@Age,@Name)";





public CreateTestObjectNonQuery(IDbProvider dbProvider)



: base(dbProvider, sql) {



DeclaredParameters.Add("Age", DbType.Int32);


DeclaredParameters.Add("Name", SqlDbType.NVarChar, 16);


Compile();


}



public void Create(string name, int age) {


ExecuteNonQuery(name, age);


}

}

Variable length arguments

StoredProcedure

ADO.NET supports discovery of Stored
Procedure parameters.

public class CallCreateTestObject : StoredProcedure {



public CallCreateTestObject(IDbProvider dbProvider)


: base(dbProvider, "CreateTestObject") {


DeriveParameters();


Compile();


}



public void Create(string name, int age) {


ExecuteNonQuery(name, age);


}

}

StoredProcedure

Easy access to out parameters

public class CallCreateTestObject : StoredProcedure {



public CallCreateTestObject(IDbProvider dbProvider)


: base(dbProvider, "CreateTestObject") {


DeriveParameters();


Compile();


}



public void Create(string name, int age) {


IDictionary inParams = new Hashtable();


inParams["name"] = name;


inParams["age"] = age;


IDictionary outParams = ExecuteNonQuery(inParams);


}

}

O/R Mapping Support

Easy ‘porting’ code/concepts from .NET versions of Java
O/R


NHibernate


IBatis.NET

Two levels of support


IoC helpers for central object injection/configuration


Template classes for resource/tx management.

Others as well….


DB40


WilsonORM


Gentle.NET


Neo


Microsoft
-

ADO.NET 3.0 LINQ for X.

NHibernate Example

public class NativeNHTestObjectDao : ITestObjectDao {


// SessionFactory property ...


public void Create(TestObject to) {


ISession session = null;


ITransaction transaction = null;




try {


session = SessionFactory.OpenSession();


transaction = session.BeginTransaction();



session.Save(to);


transaction.Commit();


} catch {


if(transaction != null) transaction.Rollback();


throw;


} finally {


if(session != null) session.Close();


}


}

}

NHibernateTemplate DAO
Implementation

public class NHTestObjectDao :
HibernateDaoSupport
,









ITestObjectDao {


[Transaction()]


public void Create(TestObject to) {


HibernateTemplate.Save(to);


}

}

Support for declarative and programmatic transaction
management for any data access technology

Microsoft Transaction Management

Local

Distributed

Declarative

Programmatic

ADO.NET (1.1)









EnterpiseServices
(1.1)










System.Transactions
(2.0)









.NET 3.0 (WinFX)









The sweet spot


Declarative transaction management + local
transactions

ADO.NET Transactions

ADO.NET


Connection/Transaction pair.


Associate multiple DbCommands with the
same transaction


API


Transaction.Begin(), Commit(), Rollback()



EnterpriseService Transactions

Access to COM+ services


MS
-
DTC for transaction management


Declarative transaction demarcation features

Cumbersome to deploy and develop


Declarative demarcation only at class level


NB: Spring.Services provides an EnterpriseServicesExporter

Originally required inheriting from
ServicedComponent

Providers are aware of transaction context of the thread


Similar to approach in Spring Template/TxMgr but part of
standard ADO.NET API.

Always uses MS
-
DTC to access database

API


ServiceDomain.Enter(), Leave; ContextUtil.SetAbort()

.NET 2.0 Transactions

Easy to use programming model

Providers are aware of transaction context of the
thread

Uses most efficient means of db access


Local transactions can be promoted to distributed


“Promotable Single Phase Enlistment” (PSPE)


Only Microsoft providers for now


SqlServer 2005, MSMQ.

API


new TransactionScope(); .Complete(), Dispose(),


Transaction.Current.Rollback()

Transaction Managers

AdoPlatformTransactionManager


Local transactions

ServiceDomainPlatformTransactionManager


Distributed transactions

TxScopePlatformTransactionManager


Local or Distributed as needed.

Switching is just a small configuration
change.

Callback interfaces


ITransactionCallback

TODOs

Use ADO.NET and O/R Mappers within in
same transaction

“KeyHolder” to easily access created keys

Custom schema for transaction mgmt

DataSet functionality

LOB support

Nested Transactions…

Summary

Spring’s approach to Data Access is very
applicable to .NET development

ADO.NET framework will give you real
productivity gains

Give it a whirl


Feedback more than welcome!


www.springframework.net

Q&A

DEMO