Question

I am using the below to create objects from a DB query:

public static T Query<T>(this MySqlConnection conn, string query) where T : new()
    {
        T obj = default(T);
        conn.Open();
        using (MySqlCommand command = new MySqlCommand(query, conn))
        {
            using (MySqlDataReader reader = command.ExecuteReader())
            {
                while (reader.Read())
                {
                    obj = new T();

                    PropertyInfo[] propertyInfos;
                    propertyInfos = typeof(T).GetProperties();

                    for (int i = 0; i < reader.FieldCount; i++)
                    {
                        var name = reader.GetName(i);

                        foreach (var item in propertyInfos)
                        {
                            if (item.Name.Equals(name, StringComparison.InvariantCultureIgnoreCase) && item.CanWrite)
                            {
                                item.SetValue(obj, reader[i], null);
                            }
                        }

                    }
                }
            }
        }
        conn.Dispose();

        return obj;
    }

I am aware of libraries out there for this and use of linq etc. But what I am really after here is the effective reverse of the above. I want to pass it an object and have it inserted into the database but cannot quite figure it out:

I have the below but cannot get the values of the objects to build the insert query:

public static T Insert<T>(this MySqlConnection conn) where T : new()
    {
        string query = "INSERT INTO " + typeof(T).Name;
        string fields = "(";
        string values = "(";

        T obj = default(T);
        conn.Open();
        using (MySqlCommand command = conn.CreateCommand())
        {
            obj = new T();

            PropertyInfo[] propertyInfos;
            propertyInfos = typeof(T).GetProperties();

            command.CommandText = query;
            command.ExecuteNonQuery();
        }
        conn.Close();

        return obj;

    }

Help appreciated. I just want an insert query built from a passed object. First part works fine with the below class to select from a property table:

public class Property : ManagedObject
{
    private int id; //(most sites the property will have a unique ID)
    private string address;
    private string city;
    private string state;
    private string zipCode;
    private string propertyUrl;
    private string status; //Status of the Property (most have that option, and it either says “in contract” or “price reduced” (most sites will have this don’t worry about the one that don’t)
    private Propertytype type;

    private double price;
    private double squareFeet;

    private DateTime listDate; //(date it first appeared on the site or if one is given, that date)
    private DateTime yearBuilt;

    private List<PriceDrop> priceDrops;

    public Property()
    {
        priceDrops = new List<PriceDrop>();
    }

    public int ID
    {
        get { return this.id; }
        set
        {
            this.CheckPropertyChanged<int>
            ("ID", ref this.id, ref value);
        }
    }

    public string Address
    {
        get { return this.address; }
        set
        {
            this.CheckPropertyChanged<string>
            ("Address", ref this.address, ref value);
        }
    }

    public string City
    {
        get { return this.city; }
        set
        {
            this.CheckPropertyChanged<string>
            ("City", ref this.city, ref value);
        }
    }

    public string State
    {
        get { return this.state; }
        set
        {
            this.CheckPropertyChanged<string>
            ("State", ref this.state, ref value);
        }
    }

    public string ZipCode
    {   
        get { return this.zipCode; }
        set
        {
            this.CheckPropertyChanged<string>
            ("ZipCode", ref this.zipCode, ref value);
        }
    }

    public string PropertyUrl
    {   
        get { return this.propertyUrl; }
        set
        {
            this.CheckPropertyChanged<string>
            ("PropertyUrl", ref this.propertyUrl, ref value);
        }
    }

    public string Status
    {   
        get { return this.status; }
        set
        {
            this.CheckPropertyChanged<string>
            ("Status", ref this.status, ref value);
        }
    }

    public Propertytype Type
    {
        get { return this.type; }
        set
        {
            this.CheckPropertyChanged<Propertytype>
            ("Type", ref this.type, ref value);
        }

    }

    public double Price
    {
        get { return this.price; }
        set
        {
            this.CheckPropertyChanged<double>
            ("Price", ref this.price, ref value);
        }
    }

    public double SquareFeet
    {   
        get { return this.squareFeet; }
        set
        {
            this.CheckPropertyChanged<double>
            ("SquareFeet", ref this.squareFeet, ref value);
        }
    }

    public DateTime ListDate
    {
        get { return this.listDate; }
        set
        {
            this.CheckPropertyChanged<DateTime>
            ("ListDate", ref this.listDate, ref value);
        }
    }

    public DateTime YearBuilt
    {
        get { return this.yearBuilt; }
        set
        {   
            this.CheckPropertyChanged<DateTime>
            ("YearBuilt", ref this.yearBuilt, ref value);
        }
    }

    public List<PriceDrop> PriceDrops
    {
        get { return this.priceDrops; }
        set
        {
            this.CheckPropertyChanged<List<PriceDrop>>
            ("PriceDrops", ref this.priceDrops, ref value);
        }
    }

}

var query = ObjectFactory.Query<Property>(AppSettings.Instance.MySqlConn, "SELECT * FROM Property");

Now I just need the insert.

Was it helpful?

Solution 2

I did eventually come back to this on a current project and have sorted out what I wanted to do, the below is for Sql Database connections and inserts in a table the object who shares the same name and field values so I dont have to write an insert for any object ever again:

public static void Insert(this SqlConnection conn, object p)
        {
            string query = "INSERT INTO {0} ({1}) VALUES ({2})";
            conn.Open();

            using (SqlCommand command = conn.CreateCommand())
            {
                PropertyInfo[] propertyInfos;
                propertyInfos = p.GetType().GetProperties();

                var objF = String.Join(",", propertyInfos.Select(i => i.Name).ToArray());
                //var objV = String.Join(",", propertyInfos.Select(i => i.GetValue(p, null)).ToArray());

                var objV = "";
                string[] array = new string[p.GetType().GetProperties().Count()];
                foreach (PropertyInfo info in p.GetType().GetProperties())
                {
                    if (info.GetValue(p,null).GetType() == typeof(string))
                    {
                        objV += "'"+(string)info.GetValue(p, null) + "',";
                    }
                    else if (info.GetValue(p, null).GetType() == typeof(DateTime))
                    {
                        objV += "CAST('" + ((DateTime)info.GetValue(p, null)).ToString("yyyy-MM-dd hh:mm:ss")+ "' AS DATETIME),";
                    }
                    else if (info.GetValue(p, null).GetType() == typeof(bool))
                    {
                        objV += "'" + ((bool)info.GetValue(p, null) == true ? "1" : "0") +"',";
                    }
                    else
                    {
                        objV += "'" + (string)info.GetValue(p, null) + "',";
                    }
                }

                command.CommandText = string.Format(string.Format(query, p.GetType().Name, objF, objV.TrimEnd(new char[] { ',' })));
                command.ExecuteNonQuery();
            }
            conn.Close();

        }

Here is a quick example of its use with a Call table and object:

Business.Objects.Call c = new Business.Objects.Call();
            c.Number = "07889876774";
            c.StartTime = DateTime.Now;
            c.EndTime = DateTime.Now.AddHours(1);
            ObjectFactory.Insert(AppSettings.Instance.SqlConn, c);

Freakin Booya.

OTHER TIPS

I think what you are looking for is a Micro ORM like Dapper-dot-net. You could use Microsoft's Entity Framework, but it seems pretty heavy handed for your scenario. I think a Micro ORM like dapper is the way to go.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top