简体   繁体   中英

Generating SQL insert statement using classes

I have a query regarding generating SQL insert statement using c# classes. So I have a class called students.

There is a function which gets list of students and dump that in database.

Student Model

public class Student
{
    public string ID { get; set; } = ""; // DB column name is studentID
    public string Name { get; set; } = ""; // DB column name is studentName
    public string address { get; set; } // DB column name is studentAddress
}

Function to dump Data

public async Task<Error> DumpStudentAsync()
{
    List<Student> students = new List<Student>();

    StringBuilder query = new StringBuilder();

    query = query.Append("INSERT INTO Student(studentID,studentName,studentAddress) VALUES");
    string columnList = "(@studentID{0},@studentName{0},@studentAddress{0})";

    for (int i = 0; i < students.Count; i++)
    {
        query.AppendFormat($"{columnList},", i);
    }
    query = query.Replace(',', ';', query.Length - 1, 1);

    SqlCommand cmd = new SqlCommand
    {
        CommandText = query.ToString(),
    };
    for (int i = 0; i < students.Count; i++)
    {
        cmd.Parameters.AddWithValue($"@studentID{i}", students[i].ID);
        cmd.Parameters.AddWithValue($"@studentName{i}", students[i].Name);
        cmd.Parameters.AddWithValue($"@studentAddress{i}", students[i].address);
    }

    SQLWrapper db = new SQLWrapper(_ctx, "", DSConfig.SQLConnectionKey);
    return await db.ExecuteStatementAsync(cmd, "");
}

So here I want to make this function generic in such a way that if I add a new field in my student object there should be no code change done in my function. I tried searching the answers but I didn't get anything.

Here firstly I'm appending the insert format in query where I have hard-coded. Secondly I'm appending variables for command parameters on the basis of students count which is also hard-coded. Also the class properties and database columns names are different how can I make use of class properties as DB column names?

Can I do something like this?

StringBuilder studentQuery = new StringBuilder();
string columns = "";
// Add column list on the basis of students properties
foreach (var property in Student.Properties)
{
    columns += "property.ID,"; // It should be studentID
}

// Add variables on the basis of students count

// Add command parameters value on the basis of students count

FYI: I'm using ADO.NET code to perform DB activities not Entity framework.

you have to use reflection or use an ORM of your choice.

This is an example to generate an update statement. you have to adjust it a bit, but you should get the idea.

private string GetInsert<T>(T myObj)
{
    StringBuilder sb = new StringBuilder();
    int ctr = 0;

    Type type = typeof(T);
    StringBuilder sbQry = new StringBuilder();
    System.Reflection.PropertyInfo[] propInfo = type.GetProperties();
    foreach (var pi in propInfo)
    {
        // now you have the value of one property of your object
        var propertyValue = pi.GetValue(myObj);

        if (sbQry.ToString() == string.Empty)
            sbQry.AppendFormat("INSERT INTO {0} ({1}", 
               type.Name.Replace("Entity", string.Empty), pi.Name);
        else
        {
            sbQry.AppendFormat(", {0}", pi.Name);
            sb.Append(",");
        }
        sb.Append("{" + ctr++ + "}");
    }

    if (sbQry.ToString() != string.Empty)
        sbQry.AppendFormat(") VALUES({0})", sb.ToString());

    return sbQry.ToString();
}

This kind of automatic is not easily done. .NET is strongly typed. Unless you go into stuff like reflection or dynamic code to do it. And I would not advise it. Strong Typisation is your friend. Without it you end up in the JavaScript and PHP examples for this comic . Hint: JS does the wrong thing in both cases.

For me at least, having to do some minor changes on the frontend for changes on the Database is acceptable work. If anything that is the smalest, least dangerous part of the whole process. So I can only advise against trying this.

However for databases and only databases, stuff like Entity Framework might be a good idea. It can generate your classes from the Database.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM