开发者

IsNumeric check in linq

The following linq

var subjectMarks = (from DataRow row in objDatatable.Rows
                    select Convert.ToDecimal(row["EXM_MARKS"])).Sum();

throws an exception since some row["EXM_MARKS"] has non numeric values like AB etc. How can 开发者_如何学GoI get the sum of only numeric ones out of them?


Add where clause that filters out the records that cannot be parsed as decimals. Try:

decimal dummy;

var subjectMarks = (from DataRow row in objDatatable.Rows
                     where decimal.TryParse(row["EXM_MARKS"], out dummy)
                     select Convert.ToDecimal(row["EXM_MARKS"])).Sum();


You could create an extension method SafeConvertToDecimal and use this in your LINQ query:

var subjectMarks = (from DataRow row in objDatatable.Rows
                    select row["EXM_MARKS"].SafeConvertToDecimal()).Sum();

This extension method would look like this:

public static decimal SafeConvertToDecimal(this object obj)
{
    decimal result;
    if(!decimal.TryParse(obj.ToString(), out result))
        result = 0;

    return result;
}

This approach has the advantage that it looks clean and you aren't converting each object twice as do all other answers.  


For linq to sql queries you can use built-in SqlFunctions.IsNumeric

Source: SqlFunctions.IsNumeric


use

Decimal Z;

var subjectMarks = (from DataRow row in objDatatable.Rows
                     where Decimal.TryParse (row["EXM_MARKS"], out Z)
                     select Convert.ToDecimal(row["EXM_MARKS"])).Sum();


You can make some extensions utility class like this for elegant solution:

public static class TypeExtensions
{
    public static bool IsValidDecimal(this string s)
    {
        decimal result;
        return Decimal.TryParse(s, out result);
    }
}

and use it in this way:

var subjectMarks = (from DataRow row in objDatatable.Rows
                     where row["EXM_MARKS"].IsValidDecimal()
                     select Convert.ToDecimal(row["EXM_MARKS"])).Sum();

Hope this helps.


var subjectMarks = objDatatable.Rows.Where(row => row["EXM_MARKS"].ToString().All(char.isDigit))

part of solution is getted in: here


For LINQ to SQL queries with Entity Framework Core, ISNUMERIC function is part of EF Core 6.0 under EF.Functions

Before version 6.0, you can create a user-defined function mapping !

User-defined function mapping : Apart from mappings provided by EF Core providers, users can also define custom mapping. A user-defined mapping extends the query translation according to the user needs. This functionality is useful when there are user-defined functions in the database, which the user wants to invoke from their LINQ query for example.

await using var ctx = new BlogContext();
await ctx.Database.EnsureDeletedAsync();
await ctx.Database.EnsureCreatedAsync();

_ = await ctx.Blogs.Where(b => ctx.IsNumeric(b.Name)).ToListAsync();

public class BlogContext : DbContext
{
    public DbSet<Blog> Blogs { get; set; }

    static ILoggerFactory ContextLoggerFactory
        => LoggerFactory.Create(b => b.AddConsole().AddFilter("", LogLevel.Information));

    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
        => optionsBuilder
            .UseSqlServer(@"Server=localhost;Database=test;User=SA;Password=Abcd5678;Connect Timeout=60;ConnectRetryCount=0")
            .EnableSensitiveDataLogging()
            .UseLoggerFactory(ContextLoggerFactory);

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.HasDbFunction(IsNumericMethodInfo)
            .HasName("ISNUMERIC")
            .IsBuiltIn();
    }

    private static readonly MethodInfo IsNumericMethodInfo = typeof(BlogContext)
        .GetRuntimeMethod(nameof(IsNumeric), new[] { typeof(string) });

    public bool IsNumeric(string s) => throw new NotSupportedException();
}

public class Blog
{
    public int Id { get; set; }
    public string Name { get; set; }
}
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜