none
Creating insert, update and delete methods to a service - N-Tier System RRS feed

  • Question

  • I am  currently learning n-tier data application systems. I came across a walkthrough (Creating an N-Tier Data Application) from Microsoft Developer Network. I wanted to add other methods in the service to insert, update or delete data but I get an error.

    The following code does not work for me.

    [OperationContract]
    DataEntityTier.NORTHWNDDataSet.CustomersDataTable AddCustomer(string companyName, string contactName, string contactTitle,string address, string city, string region, string postalCode, string country, string phone,string fax);

    And in the Service1.cs, the following was the method:

    public DataEntityTier.NORTHWNDDataSet.SuppliersDataTable AddCustomer(string companyName, string contactName, string contactTitle, string address, string city, string region, string postalCode, string country, string phone, string fax)

    {
        DataAccessTier.NORTHWNDDataSetTableAdapters.CustomersTableAdapter
         CustomersTableAdapter1 = new DataAccessTier.NORTHWNDDataSetTableAdapters.CustomersTableAdapter();
         return CustomersTableAdapter1.AddCustomer(companyName, contactName, contactTitle, address, city, region, postalCode, country, phone, fax);
     }


    Error: No overload for method 'AddCustomer' takes 10 arguments. Can someone please explain to me what am doing wrong? Thank you.



    Friday, December 15, 2017 2:20 PM

All replies

  • A table adapter is generated code. It is not a part of the framework code.

    An AddCustomer method implies that there is generated in the table adapter a method AddCustomer, which takes in this case 10 arguments. It seems you have generated one with less than 10.

    Normally you can see that using the intelisence by the way. 

    However, it is not something somebody not knowing what you have generated can tell you because it is not framework code. 


    Success
    Cor

    Friday, December 15, 2017 2:39 PM
  • Error: No overload for method 'AddCustomer' takes 10 arguments. Can someone please explain to me what am doing wrong? Thank you.

    You don't use datasets, datatables and table adapters with a WCF service of any type, because I see the [OperationContract] sitting there. 

    You use DTO(s) and the DTO pattern to send data through the n-tier layers sending an individual DTO or a DTO(s) in a List<DTO> collection.

    https://www.codeproject.com/Articles/1050468/Data-Transfer-Object-Design-Pattern-in-Csharp

    Why the DTO and a collection and not a datatable?

    https://dzone.com/articles/reasons-move-datatables

    http://lauteikkehn.blogspot.com/2012/03/datatable-vs-list.html

    You should learn how to use ADO.NET with SQL Command objects, datareader, parametrized in-line T-SQL or Stored Procedure in using the DTO pattern

    Example of DTO being used in the DAL that is setting behind a WCF service, which are kept in a project called Entities, and all projects have reference to Entities that need to know about the DTO(s). The example you see just happens to be using Entity Framework.

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Data.Entity;
    using System.Data.Entity.Core.EntityClient;
    using System.Data.Entity.Core.Objects;
    using System.Data.Entity.Infrastructure;
    using System.Data.SqlClient;
    using Entities;
    using DAL.Model;
    
    namespace DAL.DAO
    {
        public class DAOStudent : IDAOStudent
        {
            public DTOStudent GetStudentById(Int32 id)
            {
                var dto = new DTOStudent();
                using (var context = new CUDataEntities())
                {
                    var student = (context.Students.Where(a => a.StudentID == id)).SingleOrDefault();
    
                    if (student != null)
                    {
                        dto.StudentID = student.StudentID;
                        dto.FirstName = student.FirstName;
                        dto.LastName = student.LastName;
                        dto.EnrollmentDate = student.EnrollmentDate;
    
                        var enrolllments =  new DAOEnrollment().GetEntrollmentsByStudentId(id).ToList();
                        var courses = new DAOCourse().GetCoursesByStudentCourseId(student.StudentID).ToList();
    
                        dto.EnrollsandCourses = (from a in enrolllments
                                      join b in courses on a.CourseID equals b.CourseID
                        select new  DTOEnrollandCourse()
                         { Title = b.Title, Credits = b.Credits, Grade = a.Grade }).ToList();
                    }
                }
    
                return dto;
            }
            public void CreateStudent(DTOStudent dto)
            {
                using (var context = new CUDataEntities())
                {
                    var student = new Student
                    {
                        FirstName = dto.FirstName,
                        LastName = dto.LastName,
                        EnrollmentDate = dto.EnrollmentDate
                    };
    
                    context.Students.Add(student);
                    context.SaveChanges();
                }
            }
    
            public void DeleteStudent(int id)
            {
                Student student;
                using (var context = new CUDataEntities())
                {
                    student = (context.Students.Where(a => a.StudentID == id)).SingleOrDefault();
                }
    
                using (var newContext = new CUDataEntities())
                {
                    newContext.Entry(student).State = System.Data.Entity.EntityState.Deleted;
                    newContext.SaveChanges();
                }
            }
    
            public List<DTOStudent> GetStudents()
            {
               
                var dtos = new List<DTOStudent>();
    
                using (var context = new CUDataEntities())
                {
                    var students = context.Students.ToList();
    
                    foreach(var stud in students)
                    {
                        var dto = new DTOStudent
                        {
                            StudentID = stud.StudentID,
                            FirstName = stud.FirstName,
                            LastName = stud.LastName,
                            EnrollmentDate = stud.EnrollmentDate
                        };
    
                        dtos.Add(dto);
                    }
                }
    
                return dtos;
            }
    
            public void UpdateStudent(DTOStudent dto)
            {
                var student = new Student();
    
                using (var context = new CUDataEntities())
                {
                    student = (context.Students.Where(a => a.StudentID == dto.StudentID)).SingleOrDefault();
                }
    
                if (student != null)
                {
                    student.FirstName = dto.FirstName;
                    student.LastName = dto.LastName;
                    student.EnrollmentDate = dto.EnrollmentDate;
                } 
    
                using (var dbcontext = new CUDataEntities())
                {
                    if (student != null)
                    {
                        dbcontext.Entry(student).State = EntityState.Modified;
                        dbcontext.SaveChanges();
                    }
                }
            }
        }
    }
    

     
    Friday, December 15, 2017 3:58 PM
  • Hello DA924x,

    The problem is that the walkthrough doesn't cover ADO. I followed it to the latter but got stuck on the way. Paste the following in your url, my account has not been verified yet so can't add link to a post/reply. In the tutorial, I wanted to add other methods for insertion, update and delete but I get errors.

    msdn.microsoft.com/en-us/library/bb384570.aspx


    • Edited by HaglerWafula Friday, December 15, 2017 4:45 PM Was not done.
    Friday, December 15, 2017 4:43 PM
  • Please paste the following in your url, my account has not been verified yet so can't add link to a post/reply. In the tutorial, I wanted to add other methods for insertion, update and delete but I get errors.

    msdn.microsoft.com/en-us/library/bb384570.aspx

    Friday, December 15, 2017 7:10 PM
  • I would say that you should stop using the example you are using that is involving WCF. What you want to understand in the N-Tier pattern. 

    Here is a tutorial that you can use to help you learn n-tier. And it's using datatables too, but if you want responsive n-tier solutions in general, then you will stop using datatables eventually.

    The VO (value object) is the DTO.

    https://www.codeproject.com/Articles/36847/Three-Layer-Architecture-in-C-NET

    You'll see  DAO suffix on a class.

    What is a DAO?

    https://www.tutorialspoint.com/design_pattern/data_access_object_pattern.htm

    Another pattern you'll want look at is the Repository pattern.

    https://msdn.microsoft.com/en-us/library/ff649690.aspx?f=255&MSPPError=-2147217396

    http://blog.sapiensworks.com/post/2012/11/01/Repository-vs-DAO.aspx

    https://www.danylkoweb.com/Blog/creating-a-repository-pattern-without-an-orm-A9

    Here you see the example where the Repository object calls the DAO object in the DAL for CRUD operations with the database.

    using System;
    using System.Collections.Generic;
    using Entities;
    
    namespace Repository
    {
        public interface IStudentRepo
        {
            DTOStudent GetStudentById(Int32 id);
            List<DTOStudent> GetStudents();
            void CreateStudent(DTOStudent dto);
            void UpdateStudent(DTOStudent dto);
            void DeleteStudent(Int32 id);
        }
    }
    
    -----------------------------------------------
    using System;
    using System.Collections.Generic;
    using Entities;
    using DAL.DAO;
    
    namespace Repository
    {    public class StudentRepo : IStudentRepo
        {
            private IDAOStudent _daoStudent;
    
            public StudentRepo(IDAOStudent daoStudent)
            {
                _daoStudent = daoStudent;
            }
            public DTOStudent GetStudentById(int id)
            {
               return _daoStudent.GetStudentById(id);
            }
            public List<DTOStudent> GetStudents()
            {
                return _daoStudent.GetStudents();
            }
            public void CreateStudent(DTOStudent dto)
            {
                _daoStudent.CreateStudent(dto);
            }
            public void UpdateStudent(DTOStudent dto)
            {
                _daoStudent.UpdateStudent(dto);
            }
            public void DeleteStudent(int id)
            {
                _daoStudent.DeleteStudent(id);
            }
        }
    }
    

    Friday, December 15, 2017 7:31 PM
  • Let me follow your lead, I'll let you know when I succeed. Thank you in advance.
    Saturday, December 16, 2017 10:45 AM
  • Hi HaglerWafula,

    Is there any update, does it work for you. if yes, please mark the helpful reply as answer or share your solution. it will be beneficial to other communities who have the similar issue, if not, please describe it in detailed and feel free let us know.

    Best regards,

    Zhanglong Wu


    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    Monday, December 18, 2017 4:44 AM
    Moderator
  • Hello Zhanglong Wu,

    I still haven't found the solution am looking for. Been using this tutorial - [msdn.microsoft.com/en-us/library/bb384570.aspx] - sorry can't add link correctly since my account has not been verified yet. They have created three projects (DataEntityTier, DataAccessTier and DataService) in one solution, NTierWalkthrough.

    Retrieving data using methods in the service is quite easy for me. I now wanted to add or update data by creating methods in the service layer. I will really appreciate it if you take a look at the MSDN N-tier walkthrough and point me in the right direction. That walkthrough has a suggestion at the bottom of it that we Add additional methods to the service for updating data back to the database.

    I even tried this solution (stackoverflow.com/questions/25880349/how-to-use-sql-update-in-n-tier-data-application) but I still do get an error.

    CRUD example of one table like the Customers table of the northwind database will suffice. Thank you.



    • Edited by HaglerWafula Monday, December 18, 2017 9:57 AM Additional Information
    Monday, December 18, 2017 9:49 AM
  • Hi HaglerWafula,

    Based your description and related link, it seems that you want to do curd operation via TableAdapter. if so.

    #Insert

     // Create a new row.
                NorthwindDataSet.RegionRow newRegionRow;
                newRegionRow = northwindDataSet.Region.NewRegionRow();
                newRegionRow.RegionID = 5;
                newRegionRow.RegionDescription = "NorthWestern";
    
                // Add the row to the Region table
                this.northwindDataSet.Region.Rows.Add(newRegionRow);
    
                // Save the new row to the database
                this.regionTableAdapter.Update(this.northwindDataSet.Region);

    For more information, please refer to:

    https://msdn.microsoft.com/en-us/library/ms233812.aspx

    #Update

    try
                {
                    this.Validate();
                    this.customersBindingSource.EndEdit();
                    this.customersTableAdapter.Update(this.northwindDataSet.Customers);
                    MessageBox.Show("Update successful");
                }
                catch (System.Exception ex)
                {
                    MessageBox.Show("Update failed");
                }


    For more information, please refer to:

    https://msdn.microsoft.com/en-us/library/ms171933(v=vs.140).aspx

    #delete

    northwindDataSet1.Customers.Rows[0].Delete();

    For more information, please refer to:

    https://msdn.microsoft.com/en-us/library/feh3ed13.aspx

    Best regards,

    Zhanglong Wu


    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    Tuesday, December 19, 2017 5:46 AM
    Moderator
  • Hi Zhanglong Wu,

    This doesn't solve my issue yet. I'm using windows forms to perform the crud operations. The methods will be in the wcf services. Can you show me how to do it using the windows forms?

    Tuesday, December 19, 2017 4:00 PM
  • I use DataSets with WCF services all the time. I do *not*, however, use TableAdapters ... just the SqlCommand and SqlDataAdapter instead.

    Anyway, that said, you can serialize your DataSets to XML, such that your WCF methods simply accept a string parameter (which is the DataSet's XML). The method will deserialize the XML back to the appropriate DataSet and then do whatever that method is supposed to do with the DataSet (updating, inserting, querying) using SqlCommand and/or SqlDataAdapter.

    It's better than passing the DataSet instance itself as a parameter, because it can be heavyweight, whereas the XML is lightweight in comparison. Using Typed DataSets (which you are using, since you mentioned TableAdaters) makes it quite easy to serialize/deserialize with no problems.


    ~~Bonnie DeWitt [C# MVP]

    http://geek-goddess-bonnie.blogspot.com


    Tuesday, December 19, 2017 4:57 PM
    Moderator
  • I use DataSets with WCF services all the time. I do *not*, however, use TableAdapters ... just the SqlCommand and SqlDataAdapter instead.

    Really? That's a heavy lift for WCF with too much overhead with dataset and datatable attributes, along with the boxing and unboxing that occurs with a datatable.

    Datatables shouldn't be used in SOA solutions.

    Wednesday, December 20, 2017 2:12 AM
  • Hi Zhanglong Wu,

    This doesn't solve my issue yet. I'm using windows forms to perform the crud operations. The methods will be in the wcf services. Can you show me how to do it using the windows forms?

    So what are you trying to do here? Are you trying to learn WCF? Are you trying to learn n-tier?

    Myself, I think you have lost your way. You need to learn how to use and understand ntier with not involving WCF. You need to know how to develop a solution using ntier architecture.

    N-tier is just one style out of many. I suggest that you don't get side tracked in using WCF in ntier, but you should understand ntier and how to use it.

    https://msdn.microsoft.com/en-us/library/ee658117.aspx

    Wednesday, December 20, 2017 2:27 AM
  • I use DataSets with WCF services all the time. I do *not*, however, use TableAdapters ... just the SqlCommand and SqlDataAdapter instead.

    Really? That's a heavy lift for WCF with too much overhead with dataset and datatable attributes, along with the boxing and unboxing that occurs with a datatable.

    Datatables shouldn't be used in SOA solutions.

    But I'm not talking about sending and/or receiving a DataSet through WCF. It's just a string of XML ... which doesn't include the schema or anything, just the XML you get with a MyDataSet.GetXml(). I don't see how that is very much overhead.

    I guess we should agree to disagree on this topic.  ;0)


    ~~Bonnie DeWitt [C# MVP]

    http://geek-goddess-bonnie.blogspot.com

    Wednesday, December 20, 2017 2:46 AM
    Moderator
  • I use DataSets with WCF services all the time. I do *not*, however, use TableAdapters ... just the SqlCommand and SqlDataAdapter instead.

    Really? That's a heavy lift for WCF with too much overhead with dataset and datatable attributes, along with the boxing and unboxing that occurs with a datatable.

    Datatables shouldn't be used in SOA solutions.

    But I'm not talking about sending and/or receiving a DataSet through WCF. It's just a string of XML ... which doesn't include the schema or anything, just the XML you get with a MyDataSet.GetXml(). I don't see how that is very much overhead.

    I guess we should agree to disagree on this topic.  ;0)


    ~~Bonnie DeWitt [C# MVP]

    http://geek-goddess-bonnie.blogspot.com

    Sending  the bowl in any form that has to be reconstituted to be a bowl is not optimal. The bowl is the bowl.

    https://www.hanselman.com/blog/ReturningDataSetsFromWebServicesIsTheSpawnOfSatanAndRepresentsAllThatIsTrulyEvilInTheWorld.aspx

    Wednesday, December 20, 2017 4:18 AM
  • Sending  the bowl in any form that has to be reconstituted to be a bowl is not optimal. The bowl is the bowl.

    https://www.hanselman.com/blog/ReturningDataSetsFromWebServicesIsTheSpawnOfSatanAndRepresentsAllThatIsTrulyEvilInTheWorld.aspx

    Well now, Scott doesn't actually think that DataSets are the spawn of Satan. As he said, they have their place. I don't write publicly accessible Web Services ... they are all consumed by a "set" of applications that "talk" to each other. They know the structure of the Typed DataSets (because they all use the same .xsd for creating them).

    I don't want to get into an argument about the pros and cons of using Typed DataSets ... there was plenty of that in the responses generated by Scott's blog post. That post was written 13 years ago ... and I bet you can still find plenty of blog posts over the years since then that say that Typed DataSets have been getting a "bum rap" and that they are just fine to use anywhere. And then again, there are also plenty of blog posts that have just the opposite point of view.

    Pros and cons exist for any set of technologies. I just think that you should "never say never" ... a lot of it is personal preference.

    Truce?

     


    ~~Bonnie DeWitt [C# MVP]

    http://geek-goddess-bonnie.blogspot.com

    Wednesday, December 20, 2017 5:42 AM
    Moderator
  • Well now, Scott doesn't actually think that DataSets are the spawn of Satan. As he said, they have their place. I don't write publicly accessible Web Services ... they are all consumed by a "set" of applications that "talk" to each other. They know the structure of the Typed DataSets (because they all use the same .xsd for creating them).

    A dataset and a datatable  have no place as far as I am concerned not in SOA and Web based solutions. The last time I saw one being used was about two years ago maybe three in a 10 years old ASP.NET Web forms solution. And I cringed every time I had to go to the forms in the codebehind files to even deal with them. I am not into yesteryear technology, been there and done that yesteryear.

    Wednesday, December 20, 2017 9:51 AM
  • I apologize for perhaps some incoherent (or rather, incomplete) things I may have said. I've been sick for the last couple of days (just a cold, but a really nasty one). I know, not an excuse, but I thought I'd mention it. I had trouble sleeping last night because I could barely breathe, not to mention that when I can't sleep my mind goes into overdrive and I start thinking about stuff ... which probably makes it impossible to go back to sleep anyway!   ;0)
       
    My focus for the last 8 years has been strictly server-side ... but not web-based UI, just WCF Web Services. The purpose of these server-side Services is to pass around messages between servers (and/or between other Services on the same Server). You could call these Services a Bus or a Gateway (we use both terms).
      
    We also have an API that is exposed via a WCF Web Service for other kinds of apps to talk to (we typically don't write these apps), the API Service just processes what an app sends it.
      
    Now, what I missed saying yesterday is that each Service, the GatewayService and the AppService are actually pretty simple. Each Service has it's own class for passing message data ... the GatewayMessage class and the AppMessage class. Each Service has only one public method in their API: ProcessMessage(GatewayMessage) method ReceiveMessage(AppMessage) method.
      
    These two serializable message classes contain properties such as MessageType, CreateDate and MessageText along with destination and sender information and other relevant stuff. The MessageText property contains the serialized and encrypted TypedDataSet. What kind of DataSet it is depends on the MessageType contents. IOW, MessageType could be "Customer.Update" (in which case the DataSet contained in the MessageText property might be a CustomerDataSet). Or MessageType could be "Create.Order" and the DataSet might be an OrderDataSet.  Here's the cool thing about this ... the DataSet contained as encrypted XML in the MessageText property never has to be deserialized back into a DataSet until it gets to where it's going. I want to point that out because, at least in our systems, this one message could be re-directed and forwarded multiple times until it gets to where it's going. And we don't want the overhead of deserializing the XML in between "hops". And we certainly do *not* want to decrypt it before it gets to its destination!!!
       
    So, the processing in both WCF Services (Gateway and App) involves reading the MessageType from the message it gets and then doing something based on that MessageType. The Service might pass it on somewhere else and then return or it might decrypt and deserialize the DataSet and process it calling other methods which might access an instance of a DataAccess class to do the actual CRUD or queries or what have you.
       
    I know that you really don't care @DA, because of all this DataSet talk, but the underlying structure of what our Services do are not really dependent on DataSets. The process could just as easily use a serialized class (serialized into the MessageText property) ... but, after all, a DataSet *is* a class!  ;0) 
       
    I'm just hoping that the OP, @Hagler, gets something out of this discussion.

    ~~Bonnie DeWitt [C# MVP]

    http://geek-goddess-bonnie.blogspot.com

    Wednesday, December 20, 2017 3:15 PM
    Moderator