I have a C# application using ADO.Net access to a particular type of database (VistaDB) which I need to extend to optionally use a second type of database (SQL Server).
I'm unable to use Vista Entity Framework data access (which can support multiple database types) as this requires a higher version of the .NET framework than is available to most of my users. My data access functions take VistaDBConnection as ref arguments and whilst I can overload the functions to provide SqlConnection argument support, this will mean replicating a large number of data access functions.
I was wondering if it was possible to define function arguments to be either VistaDBConnection or SqlConnection types and then test for which type has been passed and provide options inside the data access routine to use either. I can do this by passing both VistaConnection and SqlConnection arguments to the data access functions but passing a single argument or variable type would be neater. However, this does break the strong typing feature of C#.
The best would be either to create an interface or a base class. Then have two concrete classes that implement this interface, one for VistaDB and one for SQL Server. You can then use some kind of factory (or Dependency Injection) to instantiate the correct class at runtime. The methods in question would then take an instance of the interface/base class and does not need to know any of the specific inner workings. For example:
interface IApplicationDatabase
{
Foo GetFoo(int id);
}
class VistaDatabase : IApplicationDatabase
{
public Foo GetFoo(int id)
{
//do VistaDB-specific things to get the Foo
}
}
class SqlServerDatabase : IApplicationDatabase
{
public Foo GetFoo(int id)
{
//do SQL Server-specific things to get the Foo
}
}
class Demo
{
public Foo GetFooFromStorage(int id, IApplicationDatabase storage)
{
//notice here we don't need any separate code depending on the
//concrete type of database
return storage.GetFoo(id);
}
}
You just need to define more generic type or we can say parent type of the both connection SQL as well as VistaDB connection like following. and then use as operator to cast and check against null to check whether cast was successful or not.
public void Connect(DbConnection dbConnection)
{
var sqlDbCon = dbConnection as SQLConnection;
if(con != null)
{
//process here for SQLConnection
}
var vistaDbCon = dbConnection as VistaDbConnection;
if(con != null)
{
//process here for VistaDbConnection
}
}
You don't need to do separate implementation in if else if all you want is available in a parent class like in this case if you just want to call connect method then you can do it like below because it does have connect method in IDbConnection.
public void Connect(IDbConnection dbConnection)
{
dbConnection.Open();
}
It would work in both the case with sql server and vistadb.
The idea is, Instead of using a class as type for the parameter, use interface as type for the parameter.
This interface will be defined by you and implemented individually for each type of connection.
Now when you pass instance of any classes implementing the interface, your code will work.
Use Interface function to call provider specific functions.
Previous two code samples added by other contributors is the correct example for that, Use any of them.
Related
I came across an example of the implementation an an interface. Portion of code is
public partial interface IDataProvider
{
DataTable GetEmployeeAbsenceDurationTypes();
void AlterEmployeeAbsenceDurationTypes(DataTable lookUpTable);
}
public partial class DataProvider : IDataProvider
{
public DataTable GetEmployeeAbsenceDurationTypes()
{
return GetEmployeeAbsenceDurationTypes((DbTransaction)null);
}
public DataTable GetEmployeeAbsenceDurationTypes(DbTransaction tran)
{
//Db Operations
}
}
My first question is about this "DbTransaction" class. Its not in my project, is it a build in class?
My second question is, why in the DataProvider (the implementing class), the function is calling another overload of itself?
DbTransaction is a common base-class for representing database transactions in ADO.NET; each actual ADO.NET provider subclasses this (typically) - for example SqlTransaction : DbTransaction (the sql-server client).
Calling an overload of self is a common way of implementing optional parameters, without code duplication prior to their addition in C# 4.0. In this case, that is essentially a pre-4.0 way of implementing:
public DataTable GetEmployeeAbsenceDurationTypes(DbTransaction tran = null) {...}
either implementation (overloads or optional parameter) allows usage of the form:
obj.GetEmployeeAbsenceDurationTypes(); // without transaction
obj.GetEmployeeAbsenceDurationTypes(tran); // with transaction
The first question is impossible to answer for sure without seeing the whole code, but it's probably referring to System.Data.Common.DbTransaction.
As for the implementation - presumably it's a way of reusing the code, that's all. If the implementation of the method with a parameter can handle a parameter value of null as "do it in a new transaction" (or whatever the behaviour of the parameterless method should be) naturally, why wouldn't you want one overload to call the other?
I am trying to use one class to handle all of my CRUD on the database by using the ExecuteSprocAccessor method of the .NET Enterprise Library with generics. In my data layer, I was trying something like this:
public static class CRUDDatabase
{
private static Database db = DatabaseFactory.CreateDatabase("ITS");
public static T SelectSingle<T>(string sprocName, int id)
{
return db.ExecuteSprocAccessor<T>(sprocName, id).First();
}
}
However, I get a build error on the return line in the SelectSingle() method that states:
'T' must be a non-abstract type with a public parameterless
constructor in order to use it as parameter 'TResult' in the generic
type or method
'Microsoft.Practices.EnterpriseLibrary.Data.DatabaseExtensions.ExecuteSprocAccessor(Microsoft.Practices.EnterpriseLibrary.Data.Database,
string, params object[])'
The idea behind the SelectSingle() method is that you pass in the stored procedure name and the record id of the object you want from the database. Eventually I would have SelectAll(), Update(), Delete(), etc. The parameters in those methods would be different, but you get the idea of what I'm trying to accomplish.
After reading that error, I am beginning to think this may be impossible, but does anyone know if this can work? Also, my fields in the database match 1:1 with the fields in my classes, so that is why I am not specifying any mappers.
Thanks
The compiler is telling you what's wrong: it's expecting a type that's got a zero-argument public constructor on it. All you've handed it is T, which it can't make any guarantees on, so it won't compile.
You need to add a generic constraint to limit the types T can be. Luckily, that's trivially easy:
public static T SelectSingle<T>(string sprocName, int id)
where T : new() // <---- here's the constraint
{
return db.ExecuteSprocAccessor<T>(sprocName, id).First();
}
That tells the compiler "Any type passed here must have a zero-argument constructor.
Implementing Interface just provide the skeleton of the method. If we know the exact signature line of that method, in this case
what is the requirement to implement Interface?
This is the case in which Interface has been implemented
interface IMy
{
void X();
}
public class My:IMy
{
public void X()
{
Console.WriteLine("Interface is implemented");
}
}
This is the case in which Interface has not been implemented
public class My
{
public void X()
{
Console.WriteLine("No Interface is implemented ");
}
}
My obj = new My();
obj.X();
Both the approaches will produce the same result.
what is the requirement to implement Interface?
The purpose of interfaces is to allow you to use two different classes as if they were the same type. This is invaluable when it comes to separation of concerns.
e.g. I can write a method that reads data from an IDataReader. My method doesn't need to know (or care) if that's a SqlDataReader, and OdbcDataReader or an OracleDataReader.
private void ReadData(IDataReader reader)
{
....
}
Now, lets say I need that method to process data coming from a non-standard data file. I can write my own object that implements IDataReader that knows how to read that file, and my method again, neither knows nor cares how that IDataReader is implemented, only that it is passed an object that implements IDataReader.
Hope this helps.
You can write multiple classes that implement an interface, then put any of them in a variable of the interface type.
This allows you to swap implementations at runtime.
It can also be useful to have a List<ISomeInterface> holding different implementations.
There are two purposes of inheritance in .net:
Allow derived classes to share the base-class implementations of common functionality
Allow derived-class objects to be substituted for base-class objects anywhere the latter would be accepted.
Unlike some languages (C++, for example) which allow multiple inheritance, .net requires every class to have precisely one parent type (Object, if nothing else). On the other hand, sometimes it's useful to have a class be substitutable for a number of unrelated types. That's where interfaces come in.
An object which implements an interface is substitutable for an instance of that declared interface type. Even though objects may only inherit from one base type, they may implement an arbitrary number of interfaces. This thus allows some of the power of multiple inheritance, without the complications and drawbacks of full multiple-inheritance support.
You've provided a very basic example, which is probably why you're having trouble understand why. Examine something like this:
public interface IDbColumn
{
int domainID { get; set; }
}
public static IEnumerable<T> GetDataByDomain<T>(
IQueryable<T> src) where T:IDbColumn
{
string url = HttpContext.Current.Request.Url.Host;
int i = url == "localhost" ? 1 : 2;
return src.Where(x => x.domainID == i|| x.domainID == 3);
}
domainID is a physical column in every table that will reference this method, but since the table type isn't known yet there's no way to have access to that variable without an interface.
Heres simple example wich helped me to understand interfaces:
interface IVehicle
{
void Go();
}
public class Car:IVehicle
{
public void Go()
{
Console.WriteLine("Drive");
}
}
public class SuperCar:IVehicle
{
public void Go()
{
Console.WriteLine("Drive fast!!");
}
}
IVehicle car = new Car();
car.Go(); //output Drive
car = new SuperCar();
car.Go(); //output Drive fast!!
Say you have three classes, A, B, C.
A needs to accept an argument. Either B or C can be passed through.
The best way to do this is create an interface that B and C share
Well interfaces are not meant to be used with just one class, they are used accross many classes to make sure that they contain a set of methods.
a good way to visualize it is to think about driver abstraction, being able to run 1 query that can be interoperated by several different database servers.
interface DatabaseDriver
{
public function connect(ConnectionDetails $details){}
public function disconnect(){}
public function query(Query $query){}
public function prepareQuery(SQLQuery $query){}
}
and then your actual drivers would use the interface so that the database object can be assured that that the selected driver is able to perform the tasks required.
class MySqlDriver extends Database implements DatabaseDriver{}
class AccessDriver extends Database implements DatabaseDriver{}
class MsSqlDriver extends Database implements DatabaseDriver{}
hope this helps.
Note: Code in PHP
I couldn't find the need of a generic class other than situations like collection of classes. Items like stack and linked list.
I can see people use it in other places also.
What do we gain using a generic class?
Well let's say you have a class that repersents a database table, you would need methods like Save(), Delete() - which work on any database table entity, and regardless of the type, they all operate the same way (a generic way).
So to solve that you could use a generic class like so:
public class BaseEntityModel<T> where T : IEntity2 // We use llblgen here
{
// ... code
// T is a generic type parameter which has to implement IEntity2.
// But we don't care what type it is.
public T Entity { get; set; }
public void Save()
{
Entity.Save(); // Save is from IEntity2
}
// ... code
}
Then for a Customer class we could go like this
public class Customer : BaseEntityModel<CustomerEntity>
{
public void Method()
{
// Entity is of type Customer entity
Entity.CustomerName = "Bob";
base.Save();
}
}
and then one for Company
public class Company : BaseEntityModel<CompanyEntity>
{
public void Method()
{
// Entity is of type Company entity
Entity.CompanyName = "My Company";
base.Save(); // Save is declared in the base class for a generic type (in this case company)
}
}
So is this code example it allows the same generic code to be used on different types of objects, and can be constrained to certain types of objects (using where T : IMyInterface)
There are more ways to constrain the type of object that can me used on. This information is on MSDN
MSDN has a pretty comprehensive article on the Advantages and Limitations of Generics. Basically, when you use generics you decrease the headache of type-checking to ensure type safety, type compatibility, etc. It's all handled for you at compile time.
They can help you to avoid code duplication -- for example, rather than writing FooMethod(int arg), FooMethod(string arg) etc., you can just write FooMethod<T>(T arg), which is cleaner and much more maintainable.
Also note that you can add constraints on generic type parameters using the where keyword. This is useful in making sure that a generic type parameter implements a certain interface, or has a default parameterless constructor, etc.
You gain code reuse - the same source code and logic, instantiated using and operating on different concrete types or combination of types. Leverage.
Generics allow you to implement type-safe routines that will work on any type that supports the operations performed in the routine. This way you don't have to define the same class or function multiple times to handle different types even though all the types would be handled exactly the same way in the source.
You are more-or-less right: apart from very weird places, you mainly use them in collections. But you use collections everywhere, so generics are a godsend.
I use System.Data.SQLite and C# for accesing SQLite databases/tables. For lazy and fast development reasons, I created my own library of classes to encapsulate some of System.Data.SQLite methods in one method, and to create many common database routines (methods) that let me reduce my work when accessing to data.
If I would inherit System.Data.SQLite library instead of referencing it would help me to optimize my work, ¿is this possible? ¿may you give an example, please?
It's possible to inherit from SQLite and make additions to some of the classes, particularly SQLiteConnection. However, you won't be able to use your own classes everywhere as SQLite will internally create a lot of classes like SQLiteCommand and SQLiteParameter and you don't have an option to tell SQLite to use your custom versions. There is a SQLiteFactory, but this is used for ADO.NET data provider integration and is not used internally by SQLite.
You're much better off keeping your methods separate. If you want them to feel like they're part of the library you can use Extension Methods
This is a great question and I didn't find much in the way of answers 7-years later! I just had to do a simple inherit and found it a little tricky (because I wasn't completely familiar with constraining a generic type). But here's what I ended up with that worked.
using SQLite; // Here using sqlite-net-pcl
using System.Collections.Generic;
namespace SQLiteEx
{
class SQLiteConnection : SQLite.SQLiteConnection
{
// Must provide a constructor with at least 1 argument
public SQLiteConnection(string path)
: base(path)
{
}
// With this class, you can automatically append
// some kind of global filter like LIMIT 1000
string mGlobalFilter = "";
public string GlobalFilter
{
set { mGlobalFilter = value; }
get { return string.IsNullOrWhiteSpace(mGlobalFilter) ? "" : " " + mGlobalFilter; }
}
// You MUST constrain the generic type with "where T : new()"
// OTHERWISE feel the wrath of:
// ===================================================================
// 'T' must be a non-abstract type with a public parameterless
// constructor in order to use it as parameter 'T' in the generic
// type or method 'SQLiteConnection.Query<T>(string, params object[])'
// ===================================================================
public List<T> Query<T>(string sql) where T : new()
{
return base.Query<T>(sql + GlobalFilter);
}
}
}