Whats the best approach (design pattern) to access database in C#? [closed] - c#

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 7 years ago.
Improve this question
I am a newber in design pattern.
Currently I am developing a system where I have a releation DB. What would be the best approach to CRUD from my DB?
My current code looks like the follow (C# code):
I defined a inteface with commons functions to all classes.
namespace Model
{
public interface ICommon
{
void insert();
void update();
void delete();
}
}
The Common class (abstract one) implements ICommon interface and few orders methods and attributes.
namespace Model
{
public abstract class Common : ICommon
{
public Guid RecId { set; get; }
public abstract void insert();
public abstract void update();
public abstract void delete();
public abstract List<Common> find();
/// <summary>
/// Insert or update the record
/// </summary>
public void save()
{
if (this.RecId == Guid.Empty)
{
this.insert();
}
else
{
this.update();
}
}
}
}
Then, the proper class (UserTable class for example) extends the Common class and implements the abstracts methods and others particulars attributes.
The way that I am doing my CRUD its from StoresProcedures and SqlParameter, SqlCommand and SqlConnection. Here it is a example:
class CustTableModel : Common
{
public string SerialNumber { set; get; }
public string ApplicationVersion { set; get; }
public string KernelVersion { set; get; }
public string Name { set; get; }
public bool Active { set; get; }
public override void insert()
{
List<SqlParameter> parameters = new List<SqlParameter>();
SqlParameter parameter;
// SerialNumber
parameter = new SqlParameter("#serialNumber", System.Data.SqlDbType.Int);
parameter.Value = this.SerialNumber;
parameters.Add(parameter);
// ApplicationVersion
parameter = new SqlParameter("#applicationVersion", System.Data.SqlDbType.Int);
parameter.Value = this.ApplicationVersion;
parameters.Add(parameter);
// KernelVersion
parameter = new SqlParameter("#kernelVersion", System.Data.SqlDbType.Int);
parameter.Value = this.KernelVersion;
parameters.Add(parameter);
// Name
parameter = new SqlParameter("#name", System.Data.SqlDbType.Int);
parameter.Value = this.Name;
parameters.Add(parameter);
// Active
parameter = new SqlParameter("#active", System.Data.SqlDbType.Bit);
parameter.Value = this.Active;
parameters.Add(parameter);
DBConn.execute("CUSTTABLE_INSERT", parameters); // The code of DBConn is below.
}
}
Just to a better understanding, here it is the DBConn class:
public class DBConn
{
protected SqlConnection sqlConnection;
protected string command { set; get; }
protected List<SqlParameter> parameters { set; get; }
protected void openConnection()
{
this.sqlConnection = new SqlConnection();
this.sqlConnection.ConnectionString = "Data Source=.\\SQLEXPRESS;Initial Catalog=JYL_SOAWS_DB;Integrated Security=True";
this.sqlConnection.Open();
}
protected void closeConnection()
{
if (this.sqlConnection.State == System.Data.ConnectionState.Open)
{
this.sqlConnection.Close();
}
}
/// <summary>
/// Executa o processo no banco.
/// </summary>
/// <returns>Quantidade de registros afetados.</returns>
protected SqlDataReader run()
{
SqlCommand command = new SqlCommand();
SqlDataReader ret;
this.openConnection();
command.CommandType = System.Data.CommandType.StoredProcedure;
command.Connection = this.sqlConnection;
command.CommandText = this.command;
if (this.parameters != null)
{
foreach (SqlParameter parameter in this.parameters)
{
command.Parameters.Add(parameter);
}
}
ret = command.ExecuteReader();
this.closeConnection();
return ret;
}
/// <summary>
/// Interface da classe à outros objetos.
/// </summary>
/// <param name="commandName">Nome da store procedure a ser executada.</param>
/// <param name="parameters">A lista com os parâmetros e valores.</param>
/// <returns>Numero de registros afetados.</returns>
public static SqlDataReader execute(string commandName, List<SqlParameter> parameters = null)
{
DBConn conn = new DBConn();
conn.command = commandName;
conn.parameters = parameters;
return conn.run();
}
}
I am pretty sure that there is a better way.
Could anyone help me? Thanks is advance.

You have hit upon two subtly different patterns here.
The first is the repository pattern - a way of abstracting away your business logic from your data access
The second is the Active Record pattern, whereby an entity is responsible for maintaining its own state in a database.
I would recommend you stay away from ActiveRecord in C# (you may or may not know about the Inversion of Control pattern right now, but it is very useful and fairly incompatible with AR).
I would suggest you look at something like dapper.net if you are starting out (I still use it in my smaller projects). It is a Micro-ORM which takes lots of the boilerplate away from using a database, without being opinionated or difficult to learn (I use and like EntityFramework & NHibernate, but they aren't anywhere as easy to pick up for a beginner).
Along with this, I would create a repository (a class with Create(Foo entity), Read(Guid entityId), Update(Foo entity) & Delete(Guid entityId) methods).
As an aside, be careful when using Guids as a primary key, as they can cause an interesting situation: Since most Guid implementations (almost always) have a non-sequential layout, and data is physically ordered by primary key, such inserts with can cause a lot of disk IO as the database reorders data pages on disk to accommodate new data inserted at some arbitrary position within the table. A good strategy for Guid generation for use as a primary key is to use a Guid Comb generator
Good Luck!

This is the best pattern. I advise not using an ORM. especially EF.
public class MyModel
{
public string Id {get;set;}
//public valuetype PropertyA {get;set;} //other properties
}
public interface IMyModelRepository
{
List<MyModel> GetModels();
MyModel GetModelById(string id);
void AddMyModel(MyModel model);
//other ways you want to get models etc
}
public class MyModelRepositorySql : IMyModelRepository
{
public List<MyModel> GetModels()
{
//SqlConnection etc etc
while (SqlDataReader.Read())
{
results.Add(this.populateModel(dr));
}
return results;
}
protected MyModel populateModel(SqlDataReader dr)
{
//map fields to datareader
}
public MyModel GetModelById(string id)
{
//sql conn etc
this.populateModel(dr);
}
}
Here's my reasoning:
Using the repository pattern allows you to inject ways of persisting your data which doesn't require a database. This is essential for unit testing, but also you will find it very useful if you can inject a mock repository into your project for integration testing.
Although ORMs might seem easy at first and save you a lot of typing, they cause problems in the long run. You only need to search stack overflow for entity framework questions to see the kind of knots people get themselves tied in when they hit a query that runs in a sub optimal way.
In any large project you will run across a data fetch requirement which requires some optimized way of retrieving data, which will muck up your carefully designed object graph/injectable generic repository or clever cutting edge ORM.
POCO objects are good. Complex objects (objects which have other objects as properties) are a pain in the arse when you attempt to serialise them or recursively add to the databases, etc. Keep your underlying data models POCO and only group them together in services or viewmodels using LINQ.
Well done for using GUID ids btw! Don't listen to those fools who think they will never run out of ints! (store as varchar(50) and let the DBA sort the indexing out) the problem with any DB generated id is you have to be able to create objects without connecting to the database.

For performing CRUD operations I would recommend Repository pattern with Entity framework.
Entity Framework is an ORM provided by microsoft. It deals with database using set of POCO Classes (Entity) to perform insert/update/delete/create operations.
To Execute queries against these entities, Language Integrated Query (LINQ) will be used. LINQ uses similar syntax of SQL and it returns database results as collection of Entities.
Here is a sample
Repository pattern with EF
Cheers!

Related

How to DRY up this code c# [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
This question does not appear to be about programming within the scope defined in the help center.
Closed 4 years ago.
Improve this question
I am working on a c# application where you can select movies from a combobox and it displays the movie info and the actors that were in it in a datagrid, gets all the information from a MySql database. Now I've googled most of what I need to learn and implement it into my code. The blocks of code look massive and were wondering if there was any way to dry it up a bit, such as what variables can I reuse if any, etc.
//film select
var queryfilmsearch = "SELECT title, description, release_year, rental_rate, length, rating FROM film WHERE title LIKE + #value";
MySqlCommand cmdfilmsearch = new MySqlCommand(queryfilmsearch, PubVar.connection);
cmdfilmsearch.Parameters.AddWithValue("#value", comBoxFilm.Text);
MySqlDataAdapter adpfilmserach = new MySqlDataAdapter(cmdfilmsearch);
DataSet dsfilmsearch = new DataSet();
adpfilmserach.Fill(dsfilmsearch);
dataGridView1.ReadOnly = true;
dataGridView1.DataSource = dsfilmsearch.Tables[0];
//actor from film select
var queryfilmactor = "SELECT first_name, last_name FROM actor INNER JOIN film_actor ON actor.actor_id = film_actor.actor_id INNER JOIN film ON film.film_id = film_actor.film_id WHERE film.title LIKE + #value";
MySqlCommand cmdfilmactor = new MySqlCommand(queryfilmactor, PubVar.connection);
cmdfilmactor.Parameters.AddWithValue("#value", comBoxFilm.Text);
MySqlDataAdapter adpfilmactor = new MySqlDataAdapter(cmdfilmactor);
DataSet dsfilmactor = new DataSet();
adpfilmactor.Fill(dsfilmactor);
dataGridView2.ReadOnly = true;
dataGridView2.DataSource = dsfilmactor.Tables[0];
It's basically the same code just different query and variable names
This is a lot of boilerplate, but it doesn't have to be.
First off, you're using your connections wrong. They implement IDisposable. You should take special care in handling them properly. This means that storing them as a variable is usually a bad idea. Open and close them as quickly as possible, and don't share them.
Second, you're using raw ADO.NET. While it's good to have an idea of how ADO.NET works (since it's the building block for most relational database code in .NET), it's better to use an abstraction. You end up writing less boilerplate. More concise, easier to read and refactor code. We often use Object Relational Mappers to accomplish this. There's two styles: Micro, and "full". There are several micro ORM's out there for .NET: Dapper, Npoco, PetaPoco etc. Stack Overflow (the website) uses Dapper. Then there's full ORM's such as Entity Framework and NHibernate.
You're using DataSet and DataTable. Those are poor abstractions. They don't follow Object Oriented Programming principles very well, they're too flexible, and they're inefficient. It's better to create custom classes and then use some form of ORM to map from your code to your custom classes.
You're also doing data access directly in your Web Forms. That's never a good idea. Database access should be done in a separate layer. That makes it easier to swap out either the data layer or the presentation layer, and makes it easier to re-use your data access code throughout other parts of your presentation layer.
Keeping all this in mind, we might end up with something like below. I chose Dapper. And I assumed Web Forms, but I think you'll get the idea no matter what your presentation layer is:
Data Repository
public class MySqlFilmRepository : IFilmRepository
{
readonly string _connectionString { get; set; }
public FilmRepsitory(string connectionString)
{
_connectionString = connectionString;
}
public List<Film> SearchFilmsByTitle(string title)
{
using (var connection = new MySqlConnection(_connectionString))
{
List<Film> films = connection.Query<Film>("SELECT title, description, release_year, rental_rate, length, rating FROM film WHERE title LIKE #Title", new { Title = title }).AsList();
return films;
}
}
public List<Actor> GetActorsForFilm(string filmTitle)
{
using (var connection = new MySqlConnection(_connectionString))
{
List<Actor> actors = connection.Query<Actor>("SELECT first_name, last_name FROM actor INNER JOIN film_actor ON actor.actor_id = film_actor.actor_id INNER JOIN film ON film.film_id = film_actor.film_id WHERE film.title LIKE #FilmTitle", new { FilmTitle = filmTitle }).AsList();
return actors;
}
}
}
public interface IFilmRepository
{
List<Film> SearchFilmsByTitle(string title);
List<Actor> GetActorsForFilm(string filmTitle);
}
Model classes
public class Film
{
public string Title { get; set; }
public string Description { get; set; }
public int ReleaseYear { get; set; }
public decimal RentalRate { get; set; }
public int Length { get; set; }
public string Rating { get; set; }
}
public class Actor
{
public string FirstName { get; set; }
public string LastName { get; set; }
}
Web Forms code:
IFilmRepository _filmRepository;
public void Page_Load (object sender, EventArgs e)
{
_filmRepository = new MySqlFilmRepository(ConfigurationManager.ConnectionStrings["MySqlConnectionString"].ConnectionString);
}
protected void SearchButton_Click(object sender, EventArgs e)
{
dataGridView1.DataSource = _filmRepository.SearchFilmsByTitle(SearchTextBox.Text);
dataGridView2.DataSource = _filmRepository.GetActorsForFilm(SearchTextBox.Text);
}
It ends up being more code, but now you have a centralized place to get your data calls, and you're handling your connections properly, and you have less boilerplate code to query your database, and it's more flexible. This is more code, but it's also not really repeating itself very much.

UpdateCommand Parameter value always a string

I am trying to update a shopping cart in my application using a gridview and a SQLDataSource control, I'm trying to set the update command parameters so that I can send values to my SQL Stored proc, but it keeps throwing an exception saying that it can't convert from nvarchar to string.
Given the below code;
ProductsDataSource.UpdateParameters.Add("Description", row.Cells[2].Text);
it seems that this method will not accept anything other than a String as it's second argument, so how can I convert that to other values to pass into my parameters?
I have already tried something like this;
int productID = int.Parse(row.Cells[1].Text);
but since that second parameter HAS to have a string argument, I can't insert it into my DB (Complaining it can't implicitly convert to string!)
you can specify parameter type on markup..
<UpdateParameters >
<asp:Parameter Name="paramName" DbType="String" Type="String" />
and you can set value on code behind.
ProductsDataSource.UpdateParameters["paramName"].DefaultValue = "parameter value";
OR you can use overloads of Add method without markup definition.
SqlDataSource1.UpdateParameters.Add("paramName", DbType.String, "parameter value");
Rather than directly answer why your code isn't working, I thought I'd present an alternative. Even if you fix your error with SqlDataSource, I believe it's bad to continue using in the long run. Using SqlDataSource as a control on your webpage sprinkles database code in your UI layer. This is very messy and we try to avoid that with modern applications. SqlDataSource also encourages magic strings instead of using strongly typed model objects.
A better alternative is to completely ditch SqlDataSource and use ADO.NET directly (perhaps through some micro-ORM such as Dapper). We can also move this logic into its own class, and follow the repository pattern. That class is best placed in a separate class library that your application then references, then you can reuse the class from other applications. I personally often have a console application so that I can test bits of my repository without having to go through the website.
Rather than having your website rely directly on this repository class though, we often work through an interface. This keeps our website from needing to directly depend on how the database logic is implemented. Often this is coupled with Dependency Injection, but that's a bit too big a subject for this post. I highly recommend you check out this excellent video about Dependency Injection.
So, here's our interface:
public interface IProductRepository
{
Product GetProductById(int id);
void UpdateProduct(Product product);
List<Product> GetAllProducts();
}
Now for the actual implementation:
public class SqlServerProductRepository: IProductRepository
{
private readonly string _connectionString;
public ProductRepository(string connectionString)
{
_connectionString = connectionString;
}
public Product GetProductById(int id)
{
using(var connection = new SqlConnection(_connectionString))
{
//QuerySingle is an extension method from Dapper
return connection.QuerySingle<Product>("select Name, Description, Id from Products where Id = #Id", new {Id = id});
}
}
public void UpdateProduct(Product product)
{
using(var connection = new SqlConnection(_connectionString))
{
//Execute is an extension method from Dapper
connection.Execute("update Products set Name = #Name, Description = #Description where Id = #Id", product);
}
}
public List<Product> GetAllProducts()
{
using(var connection = new SqlConnection(_connectionString))
{
//Query is an extension method from Dapper
//You'd likely want to implement filters/paging etc in a real world app
return connection.Query<Product>("select Name, Description, Id from Products").AsList();
}
}
}
You'll need a model class if you don't have an existing one:
public class Product
{
public int Id { get; set; }
public string Name { get; set; }
public string Description { get; set; }
}
Now the code in your website becomes much simpler:
//you can remove the direct reference to SqlServerProductRepository
//via Dependency Injection, not shown here
IProductRepository productRepository = new SqlServerProductRepository(connectionString);
var product = productRepository.GetProductById(1);
product.Description = "Updated Description";
productRepository.UpdateProduct(product);
ProductsGridView.DataSource = productRepository.GetAllProducts();
ProductsGridView.DataBind();
There's other ways you could go about implementing your repository, such as having it batch changes until you call SaveChanges etc, but this is a basic implementation.
Another advantage of abstracting your database interaction behind an interface is that you can try out different implementations without needing to change your entire website. Want to try Entity Framework? Create a new EntityFrameworkProductRepository that implements IProductRepository. What if you want to switch databases entirely? SqlLite is free and lightweight and suitable for small apps. Create a new SqlLiteProductRepository.
Try
string productID = (string)(row.Cells[1].Text)

How to achieve read/write separation with Entity Framework

I have a database setup using 'master/slave replication'. I have one master and (at least) one slave, possibly ℕ slaves. For simplicity from here on I'll talk about one master, one slave because determining which slave to use includes some business-logic not relevant to the actual problem at hand.
Here's a schematic of the setup (with ℕ slaves):
In the application (currently using Dapper) I have the following, simplified, code:
abstract class BaseRepo
{
private readonly string _readconn;
private readonly string _writeconn;
public BaseRepo(string readConnection, string writeConnection)
{
_readconn = readConnection; //Actually IEnumerable<string> for ℕ slaves
_writeconn = writeConnection;
}
private SqlConnection GetOpenConnection(string cnstring)
{
var c = new SqlConnection(cnstring);
c.Open();
return c;
}
public SqlConnection GetOpenReadConnection()
{
return this.GetOpenConnection(_readconn);
// Actually we use some business-logic to determine *which* of the slaves to use
}
public SqlConnection GetOpenWriteConnection()
{
return this.GetOpenConnection(_writeconn);
}
}
class CustomerRepo : BaseRepo
{
// ...ctor left out for brevity...
// "Read" functions use the "read" connection
public IEnumerable<Customer> ListCustomers()
{
using (var c = this.GetOpenReadConnection())
{
return c.Query<Customer>("select * from customers order by name");
}
}
// "Write" functions use the "write" connection
public void UpdateCustomer(Customer cust)
{
using (var c = this.GetOpenWriteConnection())
{
c.Execute("update customers set name = #name where id = #id", cust);
}
}
}
My question is; suppose I want to use Entity Framework ("code first", should that be relevant) instead of Dapper; how would I best go about achieving the same concept; inserts/updates/deletes are executed against the "master" database and selects are executed against a slave (or any of the slaves). Does EF support this scenario at all? What would I need to do to make this work?
Additional info: I already use 'read-only' and 'write-only' users at the SQL Server level as a 'last line of defence' to prevent any mistakes in the DAL. What I'm looking for is a method of limiting my DAL to avoid having to catch SQL Server exceptions because of 'not allowed' actions and having to go to the (incorrect) SQL server in the first place before finding out the desired action is not allowed. I could use the same approach as I do now; instantiate/use the correct DbContext in the method itself (listcustomers/updatecustomer in the above example). I get that. But that would mean I'd have to create a 'wrapper' function for each "CRUD" action on each "entity" which was kind of why I was moving from dapper to EF in the first place; simply expose a DBSet and have EF take care of the changetracking/SQL queries etc. and now, hopefully, also figure out which connectionstring to use for each action.
As proposed by others, create a read/write context by default and then create a readonly one inheriting from it.
Also be sure to implement in a partial class a constructor accepting another configuration if you wish too.
public partial class CustomerEntities : DbContext
{
protected CustomerEntities(string nameOrConnectionString):base(nameOrConnectionString)
{
}
}
public class ReadonlyCustomerEntities : CustomerEntities
{
public ReadonlyCustomerEntities ()
: base("name=ReadonlyCustomerEntities")
{
}
public override int SaveChanges()
{
// Throw if they try to call this
throw new InvalidOperationException("This context is read-only.");
}
}

how to minimize dependency between a form and a class in C#

In this sample code (C# winForms app) there is a Employee class with SearchEmployee() method and a DataService class with GetByEmployeeID() method. When searching for a employee, SearchEmployee() method will call GetByEmployeeID() method to talk to database. I have minimized the dependency between Employee class and DataService class by using constructor injection. (in its simplest way with out using an Interface)
But there is a dependency between Form class and Employee class as I new employee object from From class.
Will that dependency be a problem or isn't?
If that dependency should be avoided, What is the simplest way to achieve this?
I prefer not to use a pattern like MVP as I'm not familiar with it.
Class Form
{
public Form()
{
InitializeComponents();
}
private void btnSave_Click(object sender, EventArgs e)
{
Employee newEmp = new Employee (new DataService()); //Making a dependency
newEmp = newEmp.SearchEmployee (txtEmployeeID.Text);
txtEmployeeName.Text = newEmp.EmployeeName;
txtEmployeeAddress.Text = newEmp.EmployeeAddress;
}
}
Class Employee
{
string EmployeeID { get; set; }
string EmployeeName { get; set; }
string EmployeeAddress { get; set; }
DataService _DS;
public Employee(DataService DS) //Constructor injection of dataservice object
{
this._DS = DS;
}
public Employee SearchEmployee (string employeeID)
{
this.EmployeeID =employeeID;
DataTable DT= _DS.GetByEmployeeID(EmployeeID);
this.EmployeeName = DT.Rows[0].ItemArray[1].ToString();
this.EmployeeAddress = DT.Rows[0].ItemArray[2].ToString();
return this; //Returning an employee object to the caller
}
}
//This class responsible for database transaction
class DataService
{
public DataTable GetByEmployeeID(string employeeID)
{
using (SqlConnection newCon = new SqlConnection(db.GetConnectionString))
{
SqlCommand Cmd = new SqlCommand("SELECT..WHERE emp_id=#employeeID", newCon);
Cmd.Parameters.Add("#employeeID", SqlDbType.varChar).Value = employeeID;
newCon.Open();
SqlDataReader rdr = Cmd.ExecuteReader();
DataTable results = new DataTable();
results.Load(rdr);
return results;
}
}
}
Actually, a class representing an entity should contain information relevant to that entity.
Any method that belong to the management of the entity, like looking for a specific object, telling which ones contain a set of properties and the like should be in a different class.
To make my point clear:
You can have your "Employee" with only the 3 string properties and then an "EmployeeManager" which is responsible of searching for employees, containing a list with all employees, looking by id, etc.
That way, you objects will be only information carriers and you will brake the dependency between them.
In your case, it makes more sense to have the "SearchEmployee" method on the Data Service.
Will that dependency be a problem or isn't? - It's not a problem here until how you want to get things done.
If that dependency should be avoided..? - Yes. Your program is having only one unit of work which is GetByEmployeeID(string employeeID). Dependency Injection(DI) is supposed to use when an employee object will need some other objects like department(which becomes dependency of employee object & will be injected via constructor pattern). In your program, dependency works like a service so there is almost no possibility that it alters its behavior depending on the caller. Also DI simplifies testing/mocking objects, testing employee object will eliminate the need of testing it's dependencies i.e. department.
What is the simplest way to achieve this?. I prefer not to use a pattern like MVP as I'm not familiar with it. -
Well, simplest requires solid base/architecture, then after your program will be able to accomplish this task in quite a few lines of code. You can use ORM(object relational mapper) frameworks like Microsoft entity framework which simplifies domain/data/repository/unit-of-work part.

How to access output parameter values for IParameterMapper?

Relational Database: Sql Server 2008
Programming Language: C#
Used Framework: Enterprise Library 5.0
How do you access output parameters that are created within the implementation of IParameterMapper?
I'm currently implementing the Repository Pattern. All of our Insert stored procedures contain an output parameter. The output parameter is only present in for those tables who's primary key is an auto generated identity column. All of my stored procedures have associated implementations of IParameterMapper. Each table has an associated TransferObject. Each TransferObject has an associated IRowMapper implementation.
If it is impossible to access the output parameter I believe I only have two other options.
1) Change the stored procedures to return a row that contains the newly created identity as opposed to returning the value through an output parameter. By doing it this way I can use the currently implemented IRowMapper to access the value in the application layer. This way would be more resource intensive but less programming will be needed within the repository.
2) Don't use Database.ExecuteSprocAccessor and just execute the stored procedure "normally"; keeping the stored procedures as they are. This would be the most efficient solution, but require more programming effort.
Below is an example of how we are currently implementing things.
Current Implementation
public class UserRepository : IRepository<User>
{
....
public void Insert(User user)
{
this.database.
}
....
}
public class User : TransferObject
{
public string ID { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
}
public class UserRowMapper : IRowMapper<User>
{
private static readonly UserRowMapper instance = new UserRowMapper();
private UserRowMapper()
{
}
public UserRowMapper Instance
{
get
{
return instance;
}
}
public User MapRow(IDataRecord row)
{
var user = new User
{
ID = row.GetInt32("ID"),
FirstName = row.GetString("FirstName"),
LastName = row.GetString("LastName")
};
}
}
public class InsertUserParameterMapper : IParameterMapper
{
private static readonly InsertUserParameterMapper instance = new InsertUserParameterMapper();
public InsertUserParameterMapper()
{
}
public static InsertUserParameterMapper Instance
{
get
{
return instance;
}
}
public void AssignParameters(DBCommand command, object[] parameterValues)
{
var firstNameParameter = command.CreateParameter();
firstNameParameter.ParameterName = "#firstName";
firstNameParameter.Direction = ParameterDirection.Input;
parameter.Value = parameterValues[0];
command.Parameters.Add(firstNameParameter);
var lastNameParameter = command.CreateParameter();
lastNameParameter.ParameterName = "#lastName";
lastNameParameter.Direction = ParameterDirection.Input;
parameter.Value = parameterValues[1];
command.Parameters.Add(lastNameParameter);
var idParameter = command.CreateParameter();
idParameter.ParameterName = "#id";
idParameter.Direction = ParameterDirection.Output;
command.Parameters.Add(idParameter);
}
}
Output parameters were explicitly not included in the accessor design. If your sproc uses them, you're much better off calling the sproc directly.
Considering you're using this with an insert sproc, I suspect it's not returning rows anyway, so the accessor is really not the right abstraction. You want a straight sproc call.
Having said that, you can still use your input mapper if you want - it doesn't have any particular dependency on an accessor, you could call it directly, passing a DbCommand object instead. But db.ExecuteNonQuery does effectively what you're doing already anyway, so you might just get shorter code out of the deal.

Categories