Skip to content

Add SQL-InsertAndSelect with associated test project - #2

Open
kendaleiv wants to merge 1 commit into
mainfrom
sql-insert-and-select
Open

Add SQL-InsertAndSelect with associated test project#2
kendaleiv wants to merge 1 commit into
mainfrom
sql-insert-and-select

Conversation

@kendaleiv

Copy link
Copy Markdown
Owner

No description provided.

@kendaleiv kendaleiv left a comment

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I left comments throughout. There's a security concern we must address. Could we add a basic description for the pull request too?

var cmdText = "SELECT TestColumn FROM TestTable";
if (condition != null)
{
cmdText += $" WHERE {condition}";

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🚨This is a SQL injection issue. We should use SqlParameter or similar as in the Insert method in this class. One way to do this would be to create a string that contains the parameters. It might make sense to update the string? condition to be another type with that to make the constructing of the parametrized string easier.


namespace SQL_InsertAndSelect.Tests
{
public class SqlOperationsTests : IAsyncLifetime

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good job using IAsyncLifetime here, rather than IAsyncDisposable, as xUnit v2 does not call IAsyncDisposable. https://xunit.net/docs/shared-context

using var conn = new SqlConnection(db.ConnectionString);
await conn.OpenAsync();
using var cmd = new SqlCommand("CREATE TABLE TestTable (TestColumn varchar(255))", conn);
await cmd.ExecuteNonQueryAsync();

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

While it's great that the database is reused between tests for better performance, the database isn't returned to the original state after each test. Ideally each test would be completely isolated from the others. Do you think dropping and recreating the tables would be a good idea, or is there a different solution we could implement?


foreach (var item in expected)
{
var cmdText = "INSERT INTO TestTable VALUES (@value)";

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: Multiple values could be inserted in a single database call. It doesn't really matter in this case though as it's test code with a list of 2 items.

using var conn = new SqlConnection(db.ConnectionString);
await conn.OpenAsync();
using var cmd = new SqlCommand("DROP TABLE TestTable", conn);
await cmd.ExecuteNonQueryAsync();

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What do you think about refactoring the ADO.NET code to reduce duplication? At a minimum we could refactor the InitializeAsync and DisposeAsync methods to reduce them to a single statement calling another method with a string.

return results;
}

public async Task Insert(string value)

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would someone using this method potentially be calling it multiple times in a row? If so, should we change the string value to params string[] values to allow multiple items to be inserted at the same time?

using var cmd = new SqlCommand(cmdText, conn);
using var reader = cmd.ExecuteReader();

var results = new List<string>();

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Constructing an in-memory list may work for a small result set, but if we anticipate large amounts of data, we may want to look into IAsyncEnumerable or something else.

}

using var cmd = new SqlCommand(cmdText, conn);
using var reader = cmd.ExecuteReader();

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We could use async here, unless there's a reason to leave it synchronous.

Suggested change
using var reader = cmd.ExecuteReader();
using var reader = await cmd.ExecuteReaderAsync();

using var reader = cmd.ExecuteReader();

var results = new List<string>();
while (reader.Read())

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We could use async here, unless there's a reason to leave it synchronous.

Suggested change
while (reader.Read())
while (await reader.ReadAsync())

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant