سؤال

Here is the query:

string query = @"INSERT INTO session (PK_Id, user_id, login_time, machine_ip, machine_fingerprint) 
                             VALUES (UUID(), @UId, @LogInTime, @MIp, @MFingerPrint);
                ";

Now I need this last inserted id back, which is a UUID generated by MySQL. As far as I read there is no select_last_insert_id() function for UUIDs!! And I read for php you could assign UUID() function first to a variable and then return that value. But how to go about that in C#?

Something like this, but not exactly:

string query = @"INSERT INTO session (PK_Id, user_id, login_time, machine_ip, machine_fingerprint) 
                             VALUES (@UUID = SELECT UUID(), @UId, @LogInTime, @MIp, @MFingerPrint);
                ";                  //how to do this here?

Here is more of my code:

string query = @"INSERT INTO session (PK_Id, user_id, login_time, machine_ip, machine_fingerprint) 
                 VALUES (@UUID = SELECT UUID(), @UId, @LogInTime, @MIp, @MFingerPrint);
                ";

try
{
    if (_conn.State != ConnectionState.Open)
        _conn.Open();
    MySqlCommand cmd = new MySqlCommand(query, _conn);
    cmd.Parameters.AddWithValue("@UId", Utility.usr.Id);
    cmd.Parameters.AddWithValue("@LogInTime", DateTime.Now);
    cmd.Parameters.AddWithValue("@MIp", GetMachineIP());
    cmd.Parameters.AddWithValue("@MFingerPrint", GetHardwareFingerPrint());

    var s= Convert.ToString(cmd.ExecuteScalar()); //this returns an empty string :(
    //I need to get it to any .NET data type, string, or Guid or byte[] or anything. 

But I need this datatype of s to be used in another WHERE clause in a query like this:

string query = @"UPDATE session SET logout_time = @LogOutTime 
                 WHERE user_id = @UId AND PK_Id = @SessionId";

try
{
    if (_conn.State != ConnectionState.Open)
        _conn.Open();
    MySqlCommand cmd = new MySqlCommand(query, _conn);
    cmd.Parameters.AddWithValue("@UId", Utility.usr.Id);
    cmd.Parameters.AddWithValue("@SessionId", s);
    cmd.Parameters.AddWithValue("@LogOutTime", DateTime.Now);
    cmd.ExecuteScalar();

Here @"SessionId" is the UUID field in the same table. So basically, how can I get the MySQL varbinary field in C# so that I could use that type to update by specifying WHERE in another query?

In MySQL table the UUID field is varbinary (I hope to see some solution that is not another php link or that is not asking me to switch to char datatype in the database :) ).

Edit: The problem here is we have already added plenty of UUIDs generated by MySQL into the table, so I'm a bit apprehensive about changing MySQL UUID to .NET Guid. If that's the only workaround, I'll consider that. Just that this is the first time we needed the inserted UUID value back so that I can update in another query another point of time.

A sub question: Is .NET Guid exactly the same thing as MySQL UUID?

هل كانت مفيدة؟

المحلول

I think you can go ahead with your earlier implementation without having to rely on MS Guid, but I fear I am too late :)

string query = @"INSERT INTO session (PK_Id, user_id, login_time, machine_ip, machine_fingerprint) 
                             VALUES (UUID(), @UId, @LogInTime, @MIp, @MFingerPrint); 
                 SELECT PK_Id FROM session WHERE login_time=@LogInTime AND machine_fingerprint=@MFingerPrint; //or something similar which gives you the exact same id - UUID
                ";

try
{
    if (_conn.State != ConnectionState.Open)
        _conn.Open();
    MySqlCommand cmd = new MySqlCommand(query, _conn);
    cmd.Parameters.AddWithValue("@UId", Utility.usr.Id);
    cmd.Parameters.AddWithValue("@LogInTime", DateTime.Now);
    cmd.Parameters.AddWithValue("@MIp", GetMachineIP());
    cmd.Parameters.AddWithValue("@MFingerPrint", GetHardwareFingerPrint());

    MySqlDataReader r = cmd.ExecuteReader();

    if (r.Read()) //ensure if it is read only once, else modify your `WHERE` clause accordingly
    {
        var s = (Guid)r[0];
    }
    //or even (Guid)cmd.ExecuteScalar() would work

Now you can query in update like this:

string query = @"UPDATE session SET logout_time = @LogOutTime 
                        WHERE user_id = @UId AND PK_Id = @SessionId";

try
{
    if (_conn.State != ConnectionState.Open)
        _conn.Open();
    MySqlCommand cmd = new MySqlCommand(query, _conn);
    cmd.Parameters.AddWithValue("@UId", Utility.usr.Id);
    cmd.Parameters.AddWithValue("@SessionId", s.ToByteArray());
    cmd.Parameters.AddWithValue("@LogOutTime", DateTime.Now);
    cmd.ExecuteNonQuery();

Note: Here I have converted the Guid variable s to byte array before querying. This is important, in WHERE clause, be it UPDATE or SELECT statements in query. I would ask you to move to binary field in MySQL table from varbinary.

Edit: If your table would grow dramatically large then inserting and selecting is a bad idea since SELECT query is an additional query being run. In that case @PinnyM's choice is better. I really do not think MySQL or any other database would have a default way to give back "custom" inserted ids which are not something database generated. So in short I advice you to not go for this..

Edit2: See this answer for getting binary value to .NET datatype. Sometimes casting do not work depending on MySQL .NET connector version..

نصائح أخرى

You can use the Guid type which is the MS implementation of UUID. You should be aware that when inserting data into the DB, you may need to convert the Guid to ByteArray if the MySQL driver isn't familiar with handling Guid's. See Store GUID in MySQL from C# for an example of this.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top