C# Use Generic Type in Interface

Use Generic Type in Interface.  Receiving error:  Type or namespace 'T' could not be found (are you missing an assembly or reference).  I want a generic return type as I can pass different models to the select statement.  Any ideas?
 public interface ISQL
    {
        Boolean InsertStatement(string sqlString);
        Boolean UpdateStatement(string sqlString); 
        Boolean DeleteStatement(string sqlString);
        List<T> SelectStatement(string sqlString); 
    }

Open in new window

LVL 2
CipherISAsked:
Who is Participating?

[Product update] Infrastructure Analysis Tool is now available with Business Accounts.Learn More

x
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

Dirk StraussSenior Full Stack DeveloperCommented:
Try

public interface ISQL<T>
{
    Boolean InsertStatement(string sqlString);
    Boolean UpdateStatement(string sqlString); 
    Boolean DeleteStatement(string sqlString);
    List<T> SelectStatement(string sqlString); 
}

Open in new window

0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
MishaProgrammerCommented:
Try to add a generic constrain to the interface:

public interface ISQL<T>
    {
        Boolean InsertStatement(string sqlString);
        Boolean UpdateStatement(string sqlString); 
        Boolean DeleteStatement(string sqlString);
        List<T> SelectStatement(string sqlString); 
    }

Open in new window

0
CipherISAuthor Commented:
What is the difference between the recommended solutions above and what I have below?
    public interface ISQL
    {
        Boolean InsertStatement(string sqlString);
        Boolean UpdateStatement(string sqlString); 
        Boolean DeleteStatement(string sqlString);
        List<T> SelectStatement<T>(string sqlString); 
    }

Open in new window

0
Learn SQL Server Core 2016

This course will introduce you to SQL Server Core 2016, as well as teach you about SSMS, data tools, installation, server configuration, using Management Studio, and writing and executing queries.

MishaProgrammerCommented:
You should add a generic constrain to the interface.

public interface ISQL<T>

Open in new window

0
CipherISAuthor Commented:
@Misha - why?
0
MishaProgrammerCommented:
ToCollection<T>, otherwise the compiler doesn't understand where this T is coming from. Do you try this code? Does it work? or not?
0
Dirk StraussSenior Full Stack DeveloperCommented:
The code that we suggested is correct and solves your problem. Have a look at this article for further reading. Also read https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/generics/generic-interfaces
0
CipherISAuthor Commented:
So, I'm trying to implement the Interface in the class and it is giving me problems with the <T>.  I want to pass in a property and not define the property in the class.  When I use the class I will pass the property.  

Getting the same error in the class.
    public interface ISQL<T>
    {
        Boolean InsertStatement(string sqlString);
        Boolean UpdateStatement(string sqlString); 
        Boolean DeleteStatement(string sqlString);
        List<T> SelectStatement(string sqlString); 
    }

Open in new window

    public class SQLData : ISQL<T>
    {
        SqlConnection SQLConn = new SqlConnection();
        SqlCommand SQLCmd = new SqlCommand();
        string strConnection = string.Empty;

        #region ISQL<T> Members

        public bool InsertStatement(string sqlString)
        {
            throw new NotImplementedException();
        }

        public bool UpdateStatement(string sqlString)
        {
            throw new NotImplementedException();
        }

        public bool DeleteStatement(string sqlString)
        {
            throw new NotImplementedException();
        }

        public List<T> SelectStatement(string sqlString)
        {
            throw new NotImplementedException();
        }

        #endregion

Open in new window

0
CipherISAuthor Commented:
Looks like below is the solution.  Testing.
    public class SQLData<T> : ISQL<T>
    {
        
        SqlConnection SQLConn = new SqlConnection();
        SqlCommand SQLCmd = new SqlCommand();
        string strConnection = string.Empty;


        #region ISQL<T> Members

        public bool InsertStatement(string sqlString)
        {
            throw new NotImplementedException();
        }

        public bool UpdateStatement(string sqlString)
        {
            throw new NotImplementedException();
        }

        public bool DeleteStatement(string sqlString)
        {
            throw new NotImplementedException();
        }

        public List<T> SelectStatement(string sqlString)
        {
            throw new NotImplementedException();
        }

        #endregion
    }

Open in new window

0
CipherISAuthor Commented:
Having issues implementing the generic.
namespace App.Patterns.Repository
{
    public interface ISQL<T>
    {
        Boolean InsertStatement(string sqlString);
        Boolean UpdateStatement(string sqlString); 
        Boolean DeleteStatement(string sqlString);
        List<T> SelectStatement(string sqlString);
        List<T> SelectSPROC(string sqlString);
    }
}

Open in new window

namespace App.Patterns.Repository
{
    public class SQLData : ISQL<T>  //Error here.  Same error as mentioned above.
    {
        SqlConnection SQLConn;
        SqlCommand SQLCmd;
        SqlDataReader SQLRdr;
        string strConnection = string.Empty;

        #region ISQL<T> Members

        public bool InsertStatement(string sqlString)
        {
            throw new NotImplementedException();
        }

        public bool UpdateStatement(string sqlString)
        {
            throw new NotImplementedException();
        }

        public bool DeleteStatement(string sqlString)
        {
            throw new NotImplementedException();
        }

        public List<T> SelectStatement(string sqlString) //Error here.  Same error as mentioned above.
        {
            throw new NotImplementedException();
        }

        public List<T> SelectSPROC<T>(string sprocName) where T:new()
        {
            List<T> result = new List<T>();

            try
            {
                using (SQLConn = new SqlConnection("Your Connection String"))
                using (SQLCmd = new SqlCommand())
                {

                    SQLCmd.CommandText = sprocName;
                    SQLCmd.CommandType = CommandType.StoredProcedure;
                    SQLCmd.Connection = SQLConn;

                    SQLConn.Open();

                    SQLRdr = SQLCmd.ExecuteReader();

                    while (SQLRdr.Read())
                    {
                        T t = new T();

                        for (int inc = 0; inc < SQLRdr.FieldCount; inc++)
                        {
                            Type type = t.GetType();
                            PropertyInfo prop = type.GetProperty(SQLRdr.GetName(inc));
                            prop.SetValue(t, SQLRdr.GetValue(inc), null);
                        }

                        result.Add(t);
                    }
                }
            }
            catch (Exception ex)
            {
            }
            finally
            {
                SQLRdr.Close();
                SQLConn.Close();
                SQLCmd.Dispose();
            }

            return result;
        }

        #endregion
    }
}

Open in new window

0
käµfm³d 👽Commented:
You'd have to make SqlData be generic too:

public class SQLData<T> : ISQL<T>

Open in new window

2
CipherISAuthor Commented:
Still having problems.  I don't know if this is the correct way to code this.  This is what I'm trying to accomplish.  I want to pass the SQL to return the correct data per datamodel.  Below are two example models.  I am attempting to use the Repository Pattern to call the correct SPROC which will return the appropriate data per model which is why I'm trying to use Generics.  I am having problems implementing it.  Can it be implemented?  Is there a better way?  Am I over thinking this?  I've indicated the errors below in public List<T> SelectSPROC(string sprocName) method.
public class Person
{
    public string Name { get; set; }
    public string Address { get; set; }
    public string City { get; set; }
    public string State { get; set; }
    public string Zip { get; set; }
}

public class Company
{
    public string Name { get; set; }
    public string Contact { get; set; }
    public string Address { get; set; }
    public string City { get; set; }
    public string State { get; set; }
    public string Zip { get; set; }
}

Open in new window

    public interface ISQL<T>
    {
        Boolean InsertStatement(string sqlString);
        Boolean UpdateStatement(string sqlString); 
        Boolean DeleteStatement(string sqlString);
        List<T> SelectStatement(string sqlString);
        List<T> SelectSPROC(string sprocName);
    }

Open in new window

public class SQLData<T> : ISQL<T>
    {
        SqlConnection SQLConn;
        SqlCommand SQLCmd;
        SqlDataReader SQLRdr;
        string strConnection = string.Empty;

        #region ISQL<T> Members

        public bool InsertStatement(string sqlString)
        {
            throw new NotImplementedException();
        }

        public bool UpdateStatement(string sqlString)
        {
            throw new NotImplementedException();
        }

        public bool DeleteStatement(string sqlString)
        {
            throw new NotImplementedException();
        }

        public List<T> SelectStatement(string sqlString)
        {
            throw new NotImplementedException();
        }

        public List<T> SelectSPROC(string sprocName) where T:new()  //HERE I RECEIVE ERROR - CONSTRAINTS ARE NOT ALLOWED ON NON-GENERIC DECLARATIONS
        {
            List<T> result = new List<T>();

            try
            {
                using (SQLConn = new SqlConnection("Your Connection String"))
                using (SQLCmd = new SqlCommand())
                {

                    SQLCmd.CommandText = sprocName;
                    SQLCmd.CommandType = CommandType.StoredProcedure;
                    SQLCmd.Connection = SQLConn;

                    SQLConn.Open();

                    SQLRdr = SQLCmd.ExecuteReader();

                    while (SQLRdr.Read())
                    {
                        T t = new T();  //HERE I GET AN ERROR - Cannot create an instance of the variable type 'T' because it does not have the new() constraint

                        for (int inc = 0; inc < SQLRdr.FieldCount; inc++)
                        {
                            Type type = t.GetType();
                            PropertyInfo prop = type.GetProperty(SQLRdr.GetName(inc));
                            prop.SetValue(t, SQLRdr.GetValue(inc), null);
                        }

                        result.Add(t);
                    }
                }
            }
            catch (Exception ex)
            {
            }
            finally
            {
                SQLRdr.Close();
                SQLConn.Close();
                SQLCmd.Dispose();
            }

            return result;
        }

        #endregion

Open in new window

0
käµfm³d 👽Commented:
You get an error on that line because the runtime can't know that T is new-able unless you tell it. You need to add a type constraint to your definition:

public class SQLData<T> : ISQL<T>
    where  T: new()

Open in new window


https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/generics/constraints-on-type-parameters
1
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
.NET Programming

From novice to tech pro — start learning today.