views:

97

answers:

5

How can i access abstract class in BLL ? i shouldn't see GenAccessor in BLL it must be private class GenAccessor . i should access Save method over _AccessorForSQL. ok?

MY BLL cs:


 public class AccessorForSQL: GenoTip.DAL._AccessorForSQL
    {
        public bool Save(string Name, string SurName, string Adress)
        {

            ListDictionary ld = new ListDictionary();
            ld.Add("@Name", Name);
            ld.Add("@SurName", SurName);
            ld.Add("@Adress", Adress);
            return **base.Save("sp_InsertCustomers", ld, CommandType.StoredProcedure);**
        }
    }

i can not access base.Save....????????

it is my DAL Layer:

namespace GenoTip.DAL
{
    public abstract class _AccessorForSQL
    {
        public abstract bool Save(string sp, ListDictionary ld, CommandType cmdType);
        public abstract bool Update();
        public abstract bool Delete();
        public abstract DataSet Select();
    }

   private class GenAccessor : _AccessorForSQL
    {
        DataSet ds;
        DataTable dt;
        public override bool Save(string sp, ListDictionary ld, CommandType cmdType)
        {
            SqlConnection con = null;
            SqlCommand cmd = null;
            SqlDataReader dr = null;
            try
            {
                con = GetConnection();
                cmd = new SqlCommand(sp, con);
                con.Open();
                cmd.CommandType = cmdType;
                foreach (string ky in ld.Keys)
                {
                    cmd.Parameters.AddWithValue(ky, ld[ky]);
                }
                dr = cmd.ExecuteReader();
                ds = new DataSet();
                dt = new DataTable();
                ds.Tables.Add(dt);
                ds.Load(dr, LoadOption.OverwriteChanges, dt);

            }
            catch (Exception exp)
            {

                HttpContext.Current.Trace.Warn("Error in GetCustomerByID()", exp.Message, exp);
            }
            finally
            {
                if (dr != null) dr.Close();
                if (con != null) con.Close();

            }
            return (ds.Tables[0].Rows.Count > 0) ? true : false;

        }
        public override bool Update()
        {
            return true;
        }
        public override bool Delete()
        {
            return true;
        }
        public override DataSet Select()
        {
            DataSet dst = new DataSet();
            return dst;
        }


        private static SqlConnection GetConnection()
        {
            string connStr = WebConfigurationManager.ConnectionStrings["ConnectionString"].ConnectionString;
            SqlConnection conn = new SqlConnection(connStr);
            return conn;
        }
A: 

You cannot call an abstract method because it does not have an implementation!

Perhaps you want a virtual method?

By the way this line:

return (ds.Tables[0].Rows.Count > 0) ? true : false;

is the same as this:

return (ds.Tables[0].Rows.Count > 0);
Oskar Kjellin
@Kurresmack - He has an abstract method that hes overriden what are you talking about ?
JonH
He calls base and that method is abstract. And he gets an error when calling base, not weird because base.Save is an abstract method
Oskar Kjellin
-1 ofcourse one can call the abstract method. At the time you have an instance of that class, *somebody* will have implemented the method in a subclass.
Peter Lillevold
Yes, I know that. but he is calling the unimplemented method by calling base.Save. You will get this error from the compiler "Cannot call an abstract base member". So please read the whole thing and don't down vote unless you know what I am talking about. Try adding that code yourself and you'll notice that what I said is correct. Sorry, just gets me annoyed because it seems like you haven't read the entire thing.
Oskar Kjellin
@Kurresmack: sorry for the hard feelings. Not intended. Call me a knitpicker, but my point is that your statement "cannot call an abstract method", is not true. Also, it is not the same as my statement: "..call the specific implementation found in the base class". Furthermore, you suggest that a virtual method is the solution. Which also, imo, is not the way of solving the problem. The solution is removing the 'base.' part, and adding `abstract` to the class declaration. And yes, I have tried this in code and it works perfectly fine.
Peter Lillevold
No problem. I'm cutting down on sugar which makes me a bit cranky :( however i still disagree that you can call an abstract method. In my opinion (any many other senior developers I asked) you cannot call an abstract method. The only thing that you actually can call is the override of the abstract method, which is not the same method. Regarding the virtual method I was thinking that he perhaps wanted some functuality in the base class as he explicitly calls that method
Oskar Kjellin
Hehe, good luck with the sugar! ...well, guess this boils down to wording, but no, I would *say* that I'm calling an abstract method, in the same way I would *say* that I'm calling a method declared in interface X. Yes, at runtime, it will be calling an actual virtual method, but for those not familiar with the notion of vtables and pointers it would be misguidance to *say* that "you cannot call an abstract method" when in fact the code you're writing clearly shows that you can.
Peter Lillevold
From the offical java documentation: "An abstract method is a method that is declared without an implementation (without braces, and followed by a semicolon)". I know this is c# but this is general OOP. How would you be able to call a method without an implementation?
Oskar Kjellin
+2  A: 

Scott Ambler: Building Object Applications That Work.

No futher comment - the whole DAL is pretty much a nice demonstration of how NOT to do it. A DAL should have NO (!) reference to the BLL at all. None. The DAL code area should not ahve ANY reference to the BLL layer at all.

In your case I strongly suggest some looks at:

  • BLToolkit
  • Nhibernate
TomTom
A: 

If you want to access the save method you simply create an instance of your DAL and call the .Save method like so:

using(GenAccessor g = new GenAccessor)
 {
   g.save(sproc, param2, param3);
 }
JonH
i need a interface i don't want to see GenAccessor in BLL how can i use?
programmerist
@programmerist - how in the world are you going to communicate to your DAL without the BLL ???? Your code makes no sense.
JonH
A: 

Your AccessorForSQL class must also be marked as abstract since you don't provide any implementation for the abstract methods in the _AccessorForSQL.

Clarification: the base keyword cannot be used here because it would indicate that you want to call the specific implementation found in the base class, which obviously doesn't exist since the method is abstract. That said, it doesn't mean you cannot call the method, you just have to drop the base keyword. And again, since you don't implement any of the abstract methods from the base class in the subclass you must mark the subclass as abstract as well. The following should work:

public abstract class AccessorForSQL: GenoTip.DAL._AccessorForSQL
{
    public bool Save(string Name, string SurName, string Adress)
    {

        ListDictionary ld = new ListDictionary();
        ld.Add("@Name", Name);
        ld.Add("@SurName", SurName);
        ld.Add("@Adress", Adress);
        return Save("sp_InsertCustomers", ld, CommandType.StoredProcedure);
    }
}
Peter Lillevold
"the base keyword cannot be used here because it would indicate that you want to call the specific implementation found in the base class, which obviously doesn't exist since the method is abstract" is exactly what i posted 2 hours before you and still you down vote me and write the same thing :/
Oskar Kjellin
A: 

You should probably consider using a default implementation in your _AccessorForSQL class. Then you dont need the GenAccessor at all.

By the way, you shouldn't really be using anything web related in your DAL. HttpContext and WebConfigurationManager should be factored out so you can use your DAL layer in other contexts such as WinForms.

namespace GenoTip.DAL
{
    public interface IAccessorForSQL
    {
        bool Delete();
        bool Save(string sp, ListDictionary ld, CommandType cmdType);
        DataSet Select();
        bool Update();
    }

    public class _AccessorForSQL : IAccessorForSQL
    {
        private DataSet ds;
        private DataTable dt;


        public virtual bool Save(string sp, ListDictionary ld, CommandType cmdType)
        {
            SqlConnection con = null;
            SqlCommand cmd = null;
            SqlDataReader dr = null;
            try
            {
                con = GetConnection();
                cmd = new SqlCommand(sp, con);
                con.Open();
                cmd.CommandType = cmdType;
                foreach (string ky in ld.Keys)
                {
                    cmd.Parameters.AddWithValue(ky, ld[ky]);
                }
                dr = cmd.ExecuteReader();
                ds = new DataSet();
                dt = new DataTable();
                ds.Tables.Add(dt);
                ds.Load(dr, LoadOption.OverwriteChanges, dt);
            }
            catch (Exception exp)
            {
                HttpContext.Current.Trace.Warn("Error in GetCustomerByID()", exp.Message, exp);
            }
            finally
            {
                if (dr != null)
                {
                    dr.Close();
                }
                if (con != null)
                {
                    con.Close();
                }
            }
            return (ds.Tables[0].Rows.Count > 0) ? true : false;
        }

        public abstract bool Update();
        public abstract bool Delete();
        public abstract DataSet Select();

        private static SqlConnection GetConnection()
        {
            string connStr = WebConfigurationManager.ConnectionStrings["ConnectionString"].ConnectionString;
            var conn = new SqlConnection("");
            return conn;
        }
    }
}
bic