Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Insert error about multithreading #303

Closed
ellenfier opened this issue Sep 2, 2022 · 3 comments
Closed

Insert error about multithreading #303

ellenfier opened this issue Sep 2, 2022 · 3 comments
Labels

Comments

@ellenfier
Copy link

I have met the problem:

MySql.Data.MySqlClient.MySqlException:“Fatal error encountered during command execution.”
MySqlException: Parameter '@i_1' must be defined.

And I noticed the key of 'dynamicParameters.ParamInfo' isn't correct. some key values are @i_1, @i_2..., and some are the name of the Property, like FirstName, LastName.

So I modified part of the code of 'SqlGeneratorImpl' for myown and now it works fine.
Like this:
'SqlGeneratorImpl.Insert(IClassMapper classMapper)'

        AllColumns = GetColumns().Select(c => new Column
        {
            Alias = c.Alias,
            ClassMapper = c.ClassMapper,
            Property = c.Property,
            SimpleAlias = $"{Configuration.Dialect.ParameterPrefix}i_{i++}",
            TableIdentity = c.TableIdentity,
            Table = c.Table
        }).ToList<IColumn>();

        //AllColumns = GetColumns().ToList();
        //AllColumns = AllColumns.Select(c => new Column
        //{
        //    Alias = c.Alias,
        //    ClassMapper = c.ClassMapper,
        //    Property = c.Property,
        //    SimpleAlias = $"{Configuration.Dialect.ParameterPrefix}i_{i++}",
        //    TableIdentity = c.TableIdentity,
        //    Table = c.Table
        //}).ToList<IColumn>();
@valfrid-ly
Copy link
Collaborator

Except for changing

AllColumns = GetColumns().ToList();
AllColumns = AllColumns.Select(c => new ColumnAllColumns = GetColumns().Select(c => new Column

for

AllColumns = GetColumns().Select(c => new Column

I see no difference in your code that justifies any change in the key

@ellenfier
Copy link
Author

Well, I use a local variable 'allColumns' instead of AllColumns and a ConcurrentDictionary to keep the columns value.

var allColumns = GetColumns().Select(c => new Column()).ToList(); // or _dictionary[classMapper]
//AllColumns = GetColumns().ToList();
//******
AllColumns = allColumns;

The method 'DapperImplementor.GetSimpleAliasFromColumnAlias(string columnAlias)' will return the value of SimpleAlias. And if it is null or empty, the key of DynamicParameter will be the PropertyInfo.Name instead of SimpleAlias.
When the method GetSimpleAliasFromColumnAlias is invoked by a thread, and at the same time AllColumns = GetColumns().ToList() is invoked by another thread, the problem happens. It's now thread safe.

I also change the method GetSimpleAliasFromColumnAlias.
like
SqlGenerator.GetColumnsByClassMapper(prop.ClassMapper).Any(c => c.Alias.Equals....

@valfrid-ly
Copy link
Collaborator

Would you be able to send a PR with your changes??

Please, don't forget to update the unit tests too.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants