Database interaction using C# without Entity Framework

亡梦爱人 提交于 2021-02-08 12:44:25

问题


I have been given an assignment where I need to display a form, data for which resides in various tables in Sql server. Requirement is strictly to not to use Entity framework or stored procedure. In such case, what are my options?

At the moment I am running some sql queries using SqlCommand object but then things are getting really complicated when it comes to fetching relational data and then allowing user to update it from the form.

What is the best way/approach in Winforms to allow view & edit of relational data?


回答1:


You can write your own simple classes for the objects you need to access / update. For the purpose of the following example, let's assume you have 2 tables:

Person

  • Person_Id INT PRIMARY KEY NOT NULL
  • Name NVARCHAR(100) NULL

Emails

  • Person_Id INT PRIMARY KEY NOT NULL
  • Email_Id INT PRIMARY KEY NOT NULL
  • Email NVARCHAR(100) NOT NULL

    public class MyProgram
    {
    
        public List<Person> ReadRecords()
        {
            // Set up your connection
            SqlConnection conn = new SqlConnection();
            conn.Open();
    
            SqlCommand cmd = new SqlCommand("SELECT * FROM Person", conn);
            SqlDataReader reader = cmd.ExecuteReader();
    
            List<Person> personRecords = new List<Person>();
    
            while (reader.Read())
            {
                Person p = new Person(reader, conn);
                personRecords.Add(p);
            }
    
            return personRecords;
        }
    
        public int UpdateRecords(IEnumerable<Person> records, SqlConnection conn)
        {
            int personsUpdated = 0;
            int recordsUpdated = 0;
    
            foreach (Person p in records)
            {
                if (p.Changed)
                {
                    recordsUpdated += p.Update(conn);
                    personsUpdated++;
                }
            }
    
            return recordsUpdated;
        }
    }
    
    public class Person
    {
        public const string SqlGetPersonEmailsCommand = "SELECT Email_Id, Email FROM Emails WHERE Person_Id = @Person_Id";
        public const string SqlUpdatePersonCommand = "UPDATE Person SET Name = @Name WHERE Id = @OriginalId";
        public const string SqlUpdatePersonEmailCommand = "UPDATE Emails SET Email = @Email WHERE Email_Id = @Email_Id";
    
        public int OriginalId { get; private set; }
    
        private bool personChanged;
        private bool emailsChanged { get { return changedEmails.Count > 0; } }
        public bool Changed { get { return personChanged || emailsChanged; } }
    
        private int _id;
        public int Id
        {
            get { return _id; }
            set
            {
                throw new Exception("Changing Id is not allowed.");
            }
        }
    
        private string _name;
    
        public string Name
        {
            get { return _name; }
            set
            {
                _name = value;
                personChanged = true;
            }
        }
    
        private List<int> changedEmails;
        private Dictionary<int, string> _emailAddresses;
        public string[] EmailAddresses
        {
            get
            {
                string[] values = new string[_emailAddresses.Count];
                _emailAddresses.Values.CopyTo(values, 0);
                return values;
            }
        }
    
        public void UpdateEmail(int emailId, string newEmail)
        {
            _emailAddresses[emailId] = newEmail;
            changedEmails.Add(emailId);
        }
    
        public Person(IDataReader reader, SqlConnection conn)
        {
            // Read ID (primary key from column 0)
            OriginalId = _id = reader.GetInt32(0);
    
            // Check if value in column 1 is Null; if so, set _name to Null, otherwise read the value
            _name = reader.IsDBNull(1) ? null : reader.GetString(1);
    
            // Now get all emails for this Person record
            SqlCommand readEmailsCmd = new SqlCommand(SqlGetPersonEmailsCommand, conn);
            readEmailsCmd.Parameters.Add("@Person_Id", SqlDbType.Int);
            readEmailsCmd.Parameters["@Person_Id"].Value = OriginalId;
    
            SqlDataReader emailReader = readEmailsCmd.ExecuteReader();
    
            changedEmails = new List<int>();
            _emailAddresses = new Dictionary<int, string>();
    
            if (emailReader.HasRows)
            {
                while (emailReader.Read())
                {
                    int emailId = emailReader.GetInt32(0);
                    string email = emailReader.GetString(1);
    
                    _emailAddresses.Add(emailId, email);
                }
            }
        }
    
    
        public int Update(SqlConnection conn)
        {
            int rowsUpdated = 0;
    
            SqlCommand command = null;
    
            // Update Person record
            if (personChanged)
            {
                command = new SqlCommand(SqlUpdatePersonCommand, conn);
    
                command.Parameters.Add("@OriginalId", SqlDbType.Int);
                command.Parameters["@OriginalId"].Value = OriginalId;
    
                command.Parameters.Add("@Name", SqlDbType.NVarChar);
                command.Parameters["@Name"].Value = _name;
    
                rowsUpdated = command.ExecuteNonQuery();
            }
    
            // Now update all related Email records
            foreach (int id in changedEmails)
            {
                command = new SqlCommand(SqlUpdatePersonEmailCommand, conn);
    
                command.Parameters.Add("@Email_Id", SqlDbType.Int);
                command.Parameters["@Email_Id"].Value = id;
    
                command.Parameters.Add("@Email", SqlDbType.NVarChar);
                command.Parameters["@Email"].Value = _emailAddresses[id];
    
                rowsUpdated = +command.ExecuteNonQuery();
            }
    
            return rowsUpdated;
        }
    }
    

The above example supports changing the Person's name and associated email addresses.




回答2:


In such case the best way by my opinion is to use Dapper. You will be very close to ADO.NET and control all SQL queries. At the same time you will not spend time on mapping functionality - because this is quite simple, but time-consuming part of the code.




回答3:


  • Question #1 is ends with "[besides Entity framework] what are my options?" and you got answers to that in the comments (Straight-up ADO.NET or NHibernate). You also know that because you said you're using a SqlCommand.

  • Question #2 is the hard one and I think that is what your instructor wants you to find out: "What is the best way/approach in Winforms to allow view & edit of relational data?"

I do a ton of UI's for relational data using the Microsoft Stack. But regardless of technology, you need a good pattern or method. The short answer (that isn't a book) is to abstract the data from the UI. That way they can work independently and also change independently.

First realize editing data and displaying data should be two different parts of your program. One method I like is to select your relation data from SQL SERVER as XML, then use an XSLT to display it:

<Customer>
    <Name>...
    <Company>...
    <Phone>...
    <BillingAddresses>
         <Address>...
         <Address>...
    <PayementMethods>
         <CreditCard>...
         <CreditCard>...
    <RecentOrders>
         <Order>...
         <Order>...
         <Order>...

You can use an XSLT to easily make this into HTML that looks like whatever you want. In this example, next to where you display each <Address> and <CreditCard> you can put EDIT/DELETE links, along with a ADD links under each section.

Clicking EDIT/DELETE/ADD would take you to a screen to modify that part of the relational data. When you go back to the screen that displays the XML as HTML you would then see the updated data.

This is good because you can easily modify your XML without recompiling your code. You can also use the XSLT to display your data in whatever layout you want. Your XML can then include literals for what is stored as codes (AMX=AMERICAN EXPRESS, etc).

Anywho, this is just one solution with no real requirements (for example supporting "UNDO", applying several changes at once, etc.).




回答4:


ADO.NET is the best option you have for Database access. It's the technology EF is based on. To display data you use data binding most of the time. For saving and retrieving data you use ADO.NET. You probably don't want to bin ADO Objects directly to the UI but would have a view model instead. But traditionally and in the docs ASP.NET DataSets are often directly bound to the UI witch is from todays view a bad programming style.




回答5:


Creating Data set will be the best option. Procedure to use Data set 1. Right click of your project, Go Add => New Item => Dataset. That is .xsd format file. 2. In that file right click inside the dataset, Agaign Add => Table Adapter. From that you need to complete your Data Connection after that select your table, start write your query. 3. once you finish creating you can directly connect your query to the class file.



来源:https://stackoverflow.com/questions/34958249/database-interaction-using-c-sharp-without-entity-framework

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!