How to access output parameter values for IParameterMapper? - c#

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.

Related

How to access CRUD operations of single db class instance without static methods

I'm new to NoSql and MongoDB. I'm using the MongoDB C# driver inside Visual Studio.
I've read in different places that it's preferable to have a single instance of your database class that maintains the connection(s) to keep everything thread safe and that it's generally a bad idea to use static classes for database CRUD operations.
At the start of my program I instantiate my database class which opens a connection. Within that class and also in derived classes I can perform CRUD operations. But now I'm in a different part of my solution (same namespace, different class) and I need to do read operations to check if a user exists. I also need to compose a new document that I then want to insert.
Now I'm in a situation where that's only possible by creating a new instance of the database class to access its CRUD methods. I want to avoid static CRUD methods (that could be accessed from other classes) because then the base class of my database connection also needs to be static. I cannot figure out how to approach this and what would be the recommended way.
From the MongoDB website:
The MongoClient instance actually represents a pool of connections to the database; you will only need one instance of class MongoClient even with multiple threads.
http://mongodb.github.io/mongo-csharp-driver/2.2/getting_started/quick_tour/
Does this mean I should create a new MongoClient everytime I need to acces the database in others parts of my program?
UPDATE
It seems I was a bit mistaken about the static properties and how they can be used. I now have it setup like this:
class Database
{
const string MongoConnection = "mongodb+srv://user:password#cluster.mongodb.net";
public static MongoClient Client { get; set; }
public static IMongoDatabase Directory { get; set; }
public static IMongoCollection<User> Collection { get; set; }
public Database()
{
Client = new MongoClient(MongoConnection);
Directory= Client.GetDatabase("studentDB");
Collection = Directory.GetCollection<User>("users");
}
public static void InsertNewUser(User user)
{
Collection.InsertOne(user);
}
public static bool EmailHasAccount(string email)
{
return Collection.Find(x => x.Email == email).FirstOrDefault() == null ? false : true;
}
public static User RetrieveUserAccount(string email)
{
return Collection.Find(x => x.Email == email).FirstOrDefault();
}
}
public class User
{
public Guid Id { get; private set; }
public string Name { get; set; }
public string Email { get; set; }
public User(string name, string email)
{
Id = Guid.NewGuid();
Name = name;
Email = email;
}
}
And in my main program I can use it like this:
var db = new Database();
var user = new User("myName", "email#address");
Database.InsertNewUser(user);
Console.WriteLine(Database.EmailHasAccount("email#address")); // returns true
Console.WriteLine(Database.RetrieveUserAccount("email#address").Name); // returns "myName"
That's exactly what I was looking for. What would be the best way to handle multiple collections? Would it be safe to change the Collection property or is it better to create separate properties? Is a Generic even possible?

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

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!

Code-First Entity Framework w/ Stored Procedure returning results from complex Full-text Searches

I am looking for design advice for the following scenario:
I have a code-first EF5 MVC application. I am building a full-text search function which will incorporate multiple weighted columns from many tables. As I cannot create view with an index from these tables (some of them contain text / binary columns), I have created a stored procedure which will output the ID of my object (eg. PersonID) and the rank associated with that object based on the search terms.
My current approach is to create a helper class for executing full text searches which call the stored procedure(s) and load all the objects from the context based on the returned IDs.
My questions are:
Does my approach seem sensible / follow reasonable best practice?
Has anyone else done something similar with any lessons learned?
Is there a way to do this more efficiently (i.e. have the results of the stored procedure return/map to the entities directly without an additional look-up required?)
UPDATE
Moved my detailed implementation from an edit of the question into its own answer to be more in line with what is recommended frequently # meta.stackexchange.com
Seeing as you can't use SQL methods like containstable with entityframework code first which the rest of your application could be using you could be 'forced' to do something with a storedprocedure like your describe. Whether it's best practice I don't know. However it it gets the job done I don't see why it wouldn't be sensible.
Yes - I have and still am working on a project build around EF codefirst where I had to do a fairly complex search that included several search parameters marked as 'must have' and several values marked as 'nice to have' and in from that return a weighted result.
Depending on the complexity of the result set I don't think you need to do a second roundtrip to the database and I will show you a way I have been doing it below.
Bear in mind that below is simply an example:
public List<Person> GetPeople(params string[] p)
{
var people = new List<Person>();
using (var db = new DataContext())
{
var context = ((IObjectContextAdapter)db).ObjectContext;
db.Database.Connection.Open();
var command = db.Database.Connection.CreateCommand();
command.CommandText = "SomeStoredProcedureReturningWeightedResultSetOfPeople";
command.CommandType = System.Data.CommandType.StoredProcedure;
//Add parameters to command object
people = context.Translate<Person>(command.ExecuteReader()).ToList();
}
return people;
}
Even though the storedprocedure will have a column for the weight value it won't get mapped when you translate it.
You could potentially derive a class from Person that includes the weight value if you needed it.
Posting this as an answer rather than an edit to my question:
Taking some of the insight provided by #Drauka's (and google) here is what I did for my initial iteration.
Created the stored procedure to do the full text searching. It was really too complex to be done in EF even if supported (as one example some of my entities are related via business logic and I wanted to group them returning as a single result). The stored procedure maps to a DTO with the entity id's and a Rank.
I modified this blogger's snippet / code to make the call to the stored procedure, and populate my DTO: http://www.lucbos.net/2012/03/calling-stored-procedure-with-entity.html
I populate my results object with totals and paging information from the results of the stored procedure and then just load the entities for the current page of results:
int[] projectIDs = new int[Settings.Default.ResultsPerPage];
foreach (ProjectFTS_DTO dto in
RankedSearchResults
.Skip(Settings.Default.ResultsPerPage * (pageNum - 1))
.Take(Settings.Default.ResultsPerPage)) {
projectIDs[index] = dto.ProjectID;
index++;
}
IEnumerable<Project> projects = _repository.Projects
.Where(o=>projectIDs.Contains(o.ProjectID));
Full Implementation:
As this question receives a lot of views I thought it may be worth while to post more details of my final solution for others help or possible improvement.
The complete solution looks like:
DatabaseExtensions class:
public static class DatabaseExtensions {
public static IEnumerable<TResult> ExecuteStoredProcedure<TResult>(
this Database database,
IStoredProcedure<TResult> procedure,
string spName) {
var parameters = CreateSqlParametersFromProperties(procedure);
var format = CreateSPCommand<TResult>(parameters, spName);
return database.SqlQuery<TResult>(format, parameters.Cast<object>().ToArray());
}
private static List<SqlParameter> CreateSqlParametersFromProperties<TResult>
(IStoredProcedure<TResult> procedure) {
var procedureType = procedure.GetType();
var propertiesOfProcedure = procedureType.GetProperties(BindingFlags.Public | BindingFlags.Instance);
var parameters =
propertiesOfProcedure.Select(propertyInfo => new SqlParameter(
string.Format("#{0}",
(object) propertyInfo.Name),
propertyInfo.GetValue(procedure, new object[] {})))
.ToList();
return parameters;
}
private static string CreateSPCommand<TResult>(List<SqlParameter> parameters, string spName)
{
var name = typeof(TResult).Name;
string queryString = string.Format("{0}", spName);
parameters.ForEach(x => queryString = string.Format("{0} {1},", queryString, x.ParameterName));
return queryString.TrimEnd(',');
}
public interface IStoredProcedure<TResult> {
}
}
Class to hold stored proc inputs:
class AdvancedFTS :
DatabaseExtensions.IStoredProcedure<AdvancedFTSDTO> {
public string SearchText { get; set; }
public int MinRank { get; set; }
public bool IncludeTitle { get; set; }
public bool IncludeDescription { get; set; }
public int StartYear { get; set; }
public int EndYear { get; set; }
public string FilterTags { get; set; }
}
Results object:
public class ResultsFTSDTO {
public int ID { get; set; }
public decimal weightRank { get; set; }
}
Finally calling the stored procedure:
public List<ResultsFTSDTO> getAdvancedFTSResults(
string searchText, int minRank,
bool IncludeTitle,
bool IncludeDescription,
int StartYear,
int EndYear,
string FilterTags) {
AdvancedFTS sp = new AdvancedFTS() {
SearchText = searchText,
MinRank = minRank,
IncludeTitle=IncludeTitle,
IncludeDescription=IncludeDescription,
StartYear=StartYear,
EndYear = EndYear,
FilterTags=FilterTags
};
IEnumerable<ResultsFTSDTO> resultSet = _context.Database.ExecuteStoredProcedure(sp, "ResultsAdvancedFTS");
return resultSet.ToList();
}

Assigning class value in constructor?

Question: I want to fill in database data into the properties and fields of an instance of a class in its constructor.
public class Profile : ProfileOverview
{
public Profile()
{ }
public Profile(long ProfileId)
{
using (System.Data.IDbCommand cmd = Settings.DAL.CreateCommand("SELECT * FROM Profiles WHERE ProfileId = #__in_profileid"))
{
Settings.DAL.AddParameter(cmd, "__in_profileid", ProfileId);
this = Settings.DAL.GetClass<Models.Profile>(cmd);
} // End Using cmd
} // End Constructor
... (some properties and fields)
}
The problem is, the compiler says that it cannot assign "this", because it is write protected.
Is it really necessary that I have to change my database abstraction layer to pass "this" to it, or can I do that somehow ?
The problem is, GetClass calls Activator.CreateInstance to create a new instance of Models.Profile, and I'd prefer to keep this that way (because GetClass is a function and not a procedure).
You cannot assign this. Consider altering your pattern like so:
public class Profile : ProfileOverview
{
public Profile()
{ }
public static Profile Get(long ProfileId)
{
using (System.Data.IDbCommand cmd = Settings.DAL.CreateCommand("SELECT * FROM Profiles WHERE ProfileId = #__in_profileid"))
{
Settings.DAL.AddParameter(cmd, "__in_profileid", ProfileId);
return Settings.DAL.GetClass<Models.Profile>(cmd);
} // End Using cmd
}
... (some properties and fields)
}
Update
Based on comments from #CodeInChaos and #weston, it's only fair that I add here that the above code is bad design. The static loader method would ideally live in a different class whose purpose it is to load your Profile. Consider the following basic example:
public class Profile : ProfileOverview
{
public Profile() { }
... (some properties and fields)
}
public class ProfileHelper
{
public Profile LoadProfileById(long ProfileId)
{
using (System.Data.IDbCommand cmd = Settings.DAL.CreateCommand("SELECT * FROM Profiles WHERE ProfileId = #__in_profileid"))
{
Settings.DAL.AddParameter(cmd, "__in_profileid", ProfileId);
return Settings.DAL.GetClass<Models.Profile>(cmd);
}
}
}

c# object/design fundamentals

Is this a standard, good practice way of doing things? Basically return a list of itself? Should the actual fields (id, title, etc) be a separate class? (I've seen people call it DTO objects)
I'm starting a project & I want to try & get some of these fundamentals down--
Thanks!!
public class Calendar
{
public int id { get; set; }
public string title { get; set; }
public List<calendar> GetAll()
{
var list = new List<calendar>();
var db = new mssql2();
db.set("s1");
string sql = #"select * from [cal]";
var dr = db.dr(sql);
while (dr.Read())
{
var e = new calendar();
e.id = (int)dr["id"];
e.title = dr["title"].ToString();
list.Add(e);
}
return list;
}
}
You seem to be mixing your Domain model with your Data Access layer.
Keep Calendar as it's own class, and maybe make another class called CalendarService or CalendarRepository that returns you a list of Calendar objects.
Here is an example:
public class Calendar
{
public Calendar() { }
public Calendar(int id, string title)
{
Id = id;
Title = title;
}
public int Id { get; set; }
public string Title { get; set; }
}
public class CalendarService
{
public static List<Calendar> GetAll()
{
var list = new List<Calendar>();
var db = new mssql2();
db.set("s1");
string sql = #"select * from [cal]";
var dr = db.dr(sql);
while (dr.Read())
{
// Use the constructor to create a new Calendar item
list.Add(new Calendar((int)dr["id"], dr["title"].ToString()));
}
return list;
}
}
The general idea is for the classes to represent domain objects, and class members various properties of those domain objects. Class functions would represent what the objects can do.
In your case, it might be more fitting to remove the get_all() to a some class abstracting database operations. Calendar would have the functionalities of a calendar (getting/setting some dates, getting skip years, getting/setting some appointments); depending of what you want to accomplish with a calendar.
You're tightly coupling data access, and your "get_all" method isn't even using anything from the object of type calendar. If, as in this case, your method doesn't use any data from the instance of the class to which it belongs, then that method should either not be there, or should be a static method. My preference would be for the former -- have a class whose intent is to retrieve a calendar or calendars from the database. It is a more sensible organization of code, is more testable, can be more easily abstracted from the data layer, and it also makes your data object more portable.

Categories