2

I have this query which returns an image stored in an MS SQL database. If I run this in SSMS (SQL Management Studio) it works perfectly and returns instantly.

select image from extra where product_id = 184

However in .NET Core MVC it doesn't return, and the SQL command simply times out and an error 500 occurs stating the SQL Command timeout. I have even gave it 10 full minutes to "return" the SQL command and it still doesn't.

[HttpGet("{id}/image")]
public object Get(int id)
{
    using (SqlConnection connection = new SqlConnection(connectionstring)) {
        using (SqlCommand sqlCommand = new SqlCommand("select top 1 image from extra where product_id = @product_id", connection))
        {
            sqlCommand.Parameters.AddWithValue("@product_id", id);
            sqlCommand.Connection.Open();
            using (SqlDataReader sqlDataReader = sqlCommand.ExecuteReader())
            {
                object img = null;

                if (sqlDataReader.HasRows)
                {
                    sqlDataReader.Read();
                    img = new
                    {
                        image = sqlDataReader["image"] == DBNull.Value ? null : "data:image/png;base64," + Convert.ToBase64String((byte[])sqlDataReader["image"])
                    };

                    return img;
                }
            }
        }
    }

    return new { error = true, message = "Unknown error in image getting" };
}

Stepping through the code in debug mode. It doesn't get past this line:

SqlDataReader sqlDataReader = sqlCommand.ExecuteReader();

This pastebin is what the SQL query returns if I run it in SSMS.

EDIT: SQL Version is Microsoft SQL Server 2017 (RTM-CU15-GDR) (KB4505225) - 14.0.3192.2 (X64) Jun 15 2019 00:45:05 Copyright (C) 2017 Microsoft Corporation Standard Edition (64-bit) on Windows Server 2012 R2 Standard 6.3 <X64> (Build 9600: ) (Hypervisor)

Deckerz
  • 2,606
  • 14
  • 33
  • 1
    if it timesout, you should extend the timeout. – Daniel A. White Sep 20 '19 at 13:30
  • @DanielA.White i have tried extending it to 10 minutes. Still fails – Deckerz Sep 20 '19 at 13:30
  • @Deckerz The constructor should store the connection string to a field, not the connection. Then you create and open it as needed. Keeping the connection around is a bad idea. – juharr Sep 20 '19 at 13:35
  • @Deckerz If you don't have a compelling reason to keep the connection always open (which you don't, and even if you did, connection pooling would already do it for you), you should declare the connection variable at the method level. Then you should put `using` around all database related objects (`SqlConnection`, `SqlCommand`, `SqlDataReader`) and remove any manual calls to `Close`, not only in this method, but everywhere. Often that alone solves such problems. – GSerg Sep 20 '19 at 13:36
  • @mason Just changed it to see if it makes a difference. It didn't, still fails. – Deckerz Sep 20 '19 at 13:36
  • I doubt this has anything to do with it, but why do you have the "top 1" in the code? – juharr Sep 20 '19 at 13:37
  • @juharr it was just while debugging think maybe it was returning more than one and it broke it (lots of large images being returned) – Deckerz Sep 20 '19 at 13:39
  • If the problem still happens with all the `using`s, provided that you have restarted the project and you have not called other methods that do not yet have `using`s, then it's time to double check that the connection string connects you to the same server and same database. If so, execute `sp_who` in SSMS while the query is running in the program and see what is blocking you. – GSerg Sep 20 '19 at 13:46
  • It is @GSerg weirdly this query works with high numbers i.e. 1254306 works but 184 doesn't. – Deckerz Sep 20 '19 at 13:47
  • could you include the code that sets the timeout? Also, when you run the query in SSMS, how long does it take to return the results? – Matt.G Sep 20 '19 at 13:49
  • @Matt.G SSMS says it takes 0.00 seconds. and i have used `sqlCommand.CommandTimeout = 60;` – Deckerz Sep 20 '19 at 13:50
  • What version of SQL Server are using? Express or Standard? Have you tried to De-Fragment the database? Intermittent results like this is usually occurs with Express when a database becomes fragmented. – jdweng Sep 20 '19 at 13:51
  • @jdweng its `Microsoft SQL Server 2017 (RTM-CU15-GDR) (KB4505225) - 14.0.3192.2 (X64) Jun 15 2019 00:45:05 Copyright (C) 2017 Microsoft Corporation Standard Edition (64-bit) on Windows Server 2012 R2 Standard 6.3 (Build 9600: ) (Hypervisor) ` – Deckerz Sep 20 '19 at 13:52
  • 1
    Have you had any luck with `sp_who` (or [alternatives](https://stackoverflow.com/q/41078457/11683))? Is your query executing or waiting? – GSerg Sep 20 '19 at 13:56
  • You are running on IIS Server. Are you running SSMS from same machine as the c# code is running? This looks like a credential issue running from a IIS. – jdweng Sep 20 '19 at 14:02
  • Yes they are both using the same connection string and are on the same machine. – Deckerz Sep 20 '19 at 14:04
  • 1
    @jdweng What makes you think it's a credential issue? I would think if he couldn't connect to the DB, we'd get a different error. He also stated in comments on a deleted answer that other queries in this app are working. Deckerz - are you using the same account for this web app as you are for SSMS? – mason Sep 20 '19 at 14:04
  • @GSerg I don't see it in the list as executing or waiting the status is runnable when its "stuck" – Deckerz Sep 20 '19 at 14:04
  • @mason yes SSMS and c# use the same account details. – Deckerz Sep 20 '19 at 14:04
  • could you try setting the command timeout to 0 (to wait indefinitely) – Matt.G Sep 20 '19 at 14:07
  • @Matt.G I have just tried that and I have tried 600 seconds. It never returns. – Deckerz Sep 20 '19 at 14:09
  • If you copied this DB access to a console app and try to run it, does it succeed? I think we need to work towards a [MCVE]. – mason Sep 20 '19 at 14:10
  • @mason Just created that all inline/hardcoded no variables. Still doesn't work. – Deckerz Sep 20 '19 at 14:16
  • Because it is a server machine I think it is credential issues. Is the code running as a service? I need to see connection string. In SSMS does it show Windows Credentials? If so the connection string should not have a MDF file and should have Integrated security = true. Also should not have user and password. Is the database attached to server. Then the connection string should NOT have ATTACH. ATTACH should only be used when the database is not attached to a server. It is already attached. – jdweng Sep 20 '19 at 14:16
  • Are you sure that you get a SQL time out? – Seyedraouf Modarresi Sep 20 '19 at 14:17
  • 1
    @jdweng its not credential issues, other urls (sql queries) on the same MVC app work fine. – Deckerz Sep 20 '19 at 14:17
  • @SeyedRaoufModarresi yes that it exception that is thrown. – Deckerz Sep 20 '19 at 14:18
  • 1
    Probably not related to your issue, but you should read over [Can we stop using AddWithValue Already?](https://blogs.msmvps.com/jcoehoorn/blog/2014/05/12/can-we-stop-using-addwithvalue-already/) and implement the advice there. – mason Sep 20 '19 at 14:21
  • Please increase executionTimeout of your asp request in web config, maybe it helps you. – Seyedraouf Modarresi Sep 20 '19 at 14:24
  • 1
    @SeyedRaoufModarresi How would that help if it's the SQL command timing out? And why are you assuming there's a web.config - this is ASP.NET Core on .NET Core. – mason Sep 20 '19 at 14:26
  • @Deckerz `runnable` means it's doing something. Does it have a non-zero value in the `blk` field? Please use https://stackoverflow.com/a/41078535/11683 to see exactly what code it is executing, and/or run the SQL profiler and catch the exact SQL that arrives at the server when you run the code. – GSerg Sep 20 '19 at 14:29
  • With same credentials? – jdweng Sep 20 '19 at 14:35
  • 1
    @jdweng Given that it [works for some parameter values](https://stackoverflow.com/questions/58029271/sql-query-in-ssms-works-but-not-in-c-sharp#comment102461675_58029271), [appears in the `sp_who` output](https://stackoverflow.com/questions/58029271/sql-query-in-ssms-works-but-not-in-c-sharp#comment102462260_58029271) and does not throw a "Login failed for user" exception, it is hardly about credentials. – GSerg Sep 20 '19 at 14:42
  • It depend on what you consider credentials. The database is an MDF file and can get locked. When the MDF file is attached to a server you show never use the MDF file in a connection string. Instead connect to the server to access the database. When the database is attached the Server owns the file and will lock out users from accessing the file. Since the server owns the file when attached I consider this a credential issue. – jdweng Sep 20 '19 at 14:50
  • 1
    @jdweng It's already been pointed out that the same query with different parameters are working, and that other queries on the site are working, and that we can see the query with sp_who. It's not a credentials problem, and you're continuing to say it is and ignoring what GSerg is saying is just making more noise on an already long comment thread. – mason Sep 20 '19 at 14:53
  • Comments are not for extended discussion; this conversation has been [moved to chat](https://chat.stackoverflow.com/rooms/199794/discussion-on-question-by-deckerz-sql-query-in-ssms-works-but-not-in-c). – Samuel Liew Sep 22 '19 at 09:14

1 Answers1

-4

Please try below.

Also put a break point on the Catch, and see what ex.Message is

try
            {
                SqlCommand sqlCommand = new SqlCommand("select top 1 image from extra where product_id = @product_id", connection);
                sqlCommand.Parameters.Add(new SqlParameter("@product_id", id));
                using (SqlDataReader sqlDataReader = sqlCommand.ExecuteReader())
                {
                    while (sqlDataReader.Read())
                    {
                        img = new
                        {
                            image = sqlDataReader["image"] == DBNull.Value ? null : "data:image/png;base64," + Convert.ToBase64String((byte[])sqlDataReader["image"])
                        };
                        connection.Close();
                        return img;
                    }
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
            }

            return new { error = true, message = "Unknown error in image getting" };
  • i was literally busy writing this before anyone started commenting. no need to downvote because im trying to help mate :) – CR Venter Sep 20 '19 at 13:43
  • 2
    @CRVenter "Trying to help" is not a valid defense. Presumably if you're here, you're trying to help, but that doesn't mean you're actually helping. It was already stated in the question what type of error it was and where the error was occurring - your answer did nothing to actually address the problem. Additionally, raw code dumps without explanation aren't very helpful. – mason Sep 20 '19 at 13:45
  • @ mason raw code dumps? maybe you're the one that needs to read again. in his original, unedited code, he was NOT using a `using` for his datareader. and if you look at my "code dump", I asked him to give this a try, and let us know what the exception message is, hence giving us a more in depth reason as to why he is getting his error – CR Venter Sep 20 '19 at 13:48
  • @CRVenter A using statement is unlikely to fix that problem - and you didn't explain in your answer why a using statement would be necessary, hence the characterization "raw code dump". And as I've already pointed out, the exception information was given *in the question*. So asking for it again is pointless. And if it hadn't been given in the question, the appropriate way to see that information would be a comment - not an answer. – mason Sep 20 '19 at 13:50
  • If you want to participate in this site, it helps to follow the rules and customs of the community. If you want to just dismiss this as me being argumentative, I can't stop you. But if you want to participate and gain additional privileges on this site, then listen to what people are telling you, and read through our [help info](https://stackoverflow.com/help). – mason Sep 20 '19 at 13:56