Skip to content

Fail to cast enum as nvarchar for Linq Contains #2453

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

Closed
nemenos opened this issue Jul 27, 2020 · 8 comments · Fixed by #2459
Closed

Fail to cast enum as nvarchar for Linq Contains #2453

nemenos opened this issue Jul 27, 2020 · 8 comments · Fixed by #2459

Comments

@nemenos
Copy link

nemenos commented Jul 27, 2020

Hello,
System.Data.SqlClient.SqlException (0x80131904): Conversion failed when converting the nvarchar value 'cash' to data type int.
is still thrown when using Contains method. for example:
query.Where(x => filter.PaymentMethods.Contains(x.PaymentMethod));
where payment method is mapped on db as a string (default):
fluentnhibernate -> Map(x => x.PaymentMethod).Not.Nullable();

thank you

ps. this happens after upgrading from 5.2.7 to 5.3.1, No code changed. I had to rollback to previous version

@nemenos
Copy link
Author

nemenos commented Jul 27, 2020

I think it's the same bug related to #2439 but not solved completely

@maca88
Copy link
Contributor

maca88 commented Jul 27, 2020

I am unable to reproduce the issue, I have tried the following query:

var filter = new
{
	Enums = new[] { EnumStoredAsString.Large }
};
var query = db.Users.Where(o => filter.Enums.Contains(o.Enum1)).ToList();

and it works fine. Does your query variable use methods like Fetch, Select or others? If so, could you provide the whole linq query?

@nemenos
Copy link
Author

nemenos commented Jul 28, 2020

Hello,
I reduced the query as much as possible, mapping as much as possibile, removed all listeners and interceptors.

sealed class FinancialMovementMap : ClassMap<FinancialMovement>
{
    public FinancialMovementMap()
    {
        Table("FinancialMovements");

        Id(x => x.Id).GeneratedBy.Assigned();
        Map(x => x.PaymentMethod);
    }
}

public class FinancialMovement
{
    public Guid Id { get; set; } = Guid.NewGuid();
    public AnalyticPaymentMethod PaymentMethod { get; set; }
}

public enum AnalyticPaymentMethod
{
    sisal,
    cash,
    creditcard,
    paypal,
    wallet,
    external,
    coupon,
    banktransfer
}

query is a simple Session.Query<T>.Where(...).ToList()
Only thing I could not remove is some (unused for that table) user types...
I really cannot figure out what could be the problem
I also tried version 5.3.0, but same problem.
I'm using SQLServer

@nemenos
Copy link
Author

nemenos commented Jul 28, 2020

Here is the failing test you can add to EnumTests under Linq folder:

[Test]
public void CanQueryWithContainsOnEnumStoredAsString_Small_1()
{
	var values = new[] { EnumStoredAsString.Small, EnumStoredAsString.Medium };
	var query = db.Users.Where(x => values.Contains(x.Enum1)).ToList();
	Assert.AreEqual(3, query.Count);
}

NHibernate.Exceptions.GenericADOException
HResult=0x80131500
Message=could not execute query
[ select user0_.UserId as userid1_13_, user0_.Name as name2_13_, user0_.InvalidLoginAttempts as invalidloginattempts3_13_, user0_.RegisteredAt as registeredat4_13_, user0_.LastLoginDate as lastlogindate5_13_, user0_.CreatedById as createdbyid6_13_, user0_.ModifiedById as modifiedbyid7_13_, user0_.Enum1 as enum8_13_, user0_.Enum2 as enum9_13_, user0_.Features as features10_13_, user0_.RoleId as roleid11_13_, user0_.Property1 as property12_13_, user0_.Property2 as property13_13_, user0_.OtherProperty1 as otherproperty14_13_, (case when user0_.Enum1 = 'Unspecified' then null else user0_.Enum1 end) as formula9_, (case when user0_.Enum2 = 0 then null else user0_.Enum2 end) as formula10_ from Users user0_ where user0_.Enum1 in (@p0 , @p1) ]
Name:p1_0_ - Value:Small Name:p1_1_ - Value:Medium
[SQL: select user0_.UserId as userid1_13_, user0_.Name as name2_13_, user0_.InvalidLoginAttempts as invalidloginattempts3_13_, user0_.RegisteredAt as registeredat4_13_, user0_.LastLoginDate as lastlogindate5_13_, user0_.CreatedById as createdbyid6_13_, user0_.ModifiedById as modifiedbyid7_13_, user0_.Enum1 as enum8_13_, user0_.Enum2 as enum9_13_, user0_.Features as features10_13_, user0_.RoleId as roleid11_13_, user0_.Property1 as property12_13_, user0_.Property2 as property13_13_, user0_.OtherProperty1 as otherproperty14_13_, (case when user0_.Enum1 = 'Unspecified' then null else user0_.Enum1 end) as formula9_, (case when user0_.Enum2 = 0 then null else user0_.Enum2 end) as formula10_ from Users user0_ where user0_.Enum1 in (@p0 , @p1)]
Source=
StackTrace:
This exception was originally thrown at this call stack:
System.Data.SqlClient.SqlConnection.OnError(System.Data.SqlClient.SqlException, bool, System.Action<System.Action>)
System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning(System.Data.SqlClient.TdsParserStateObject, bool, bool)
System.Data.SqlClient.TdsParser.TryRun(System.Data.SqlClient.RunBehavior, System.Data.SqlClient.SqlCommand, System.Data.SqlClient.SqlDataReader, System.Data.SqlClient.BulkCopySimpleResultSet, System.Data.SqlClient.TdsParserStateObject, out bool)
System.Data.SqlClient.SqlDataReader.TryHasMoreRows(out bool)
System.Data.SqlClient.SqlDataReader.TryReadInternal(bool, out bool)
System.Data.SqlClient.SqlDataReader.Read()
NHibernate.Driver.NHybridDataReader.Read() in NHybridDataReader.cs
NHibernate.Loader.Loader.DoQuery(NHibernate.Engine.ISessionImplementor, NHibernate.Engine.QueryParameters, bool, NHibernate.Transform.IResultTransformer, NHibernate.Cache.QueryCacheResultBuilder) in Loader.cs
NHibernate.Loader.Loader.DoQueryAndInitializeNonLazyCollections(NHibernate.Engine.ISessionImplementor, NHibernate.Engine.QueryParameters, bool, NHibernate.Transform.IResultTransformer, NHibernate.Cache.QueryCacheResultBuilder) in Loader.cs
NHibernate.Loader.Loader.DoList(NHibernate.Engine.ISessionImplementor, NHibernate.Engine.QueryParameters, NHibernate.Transform.IResultTransformer, NHibernate.Cache.QueryCacheResultBuilder) in Loader.cs
Inner Exception 1:
SqlException: Conversion failed when converting the nvarchar value 'Medium' to data type int.

@maca88
Copy link
Contributor

maca88 commented Jul 28, 2020

Thanks, I unintentionally tested the query on mysql where the issue does not occur. Made a fix in #2459.

@nemenos
Copy link
Author

nemenos commented Jul 28, 2020

Thank you @maca88. Do you think there will be a 5.3.2 soon?

@fredericDelaporte
Copy link
Member

fredericDelaporte commented Jul 28, 2020

Fixed by #2459.
Currently I am the one doing most releases. I am having quite a busy week, so it is unlikely I would prepare it for this week. It will more probably occurs on August the ninth.

@nemenos
Copy link
Author

nemenos commented Jul 29, 2020

Thank you @fredericDelaporte

@fredericDelaporte fredericDelaporte changed the title version 5.3.1 failed to cast enum as nvarchar for Linq Contains Fail to cast enum as nvarchar for Linq Contains Jul 30, 2020
@fredericDelaporte fredericDelaporte added this to the 5.3.2 milestone Jul 30, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants