简体   繁体   中英

C# Convert SQL query with Case statement to LINQ

I added a new column in one of my table and the result of this column depends on the result of 2 other columns. I did a update so I can fill the existing rows with information but I would also like to transform the case statement into a LINQ query for my code.

UPDATE depotProjet.Projets
        SET IdPlateformeSecteur =
            CASE
                WHEN (IdPlateforme = 1 AND IdSecteur = 1) then 1
                WHEN (IdPlateforme = 1 AND IdSecteur = 2) then 2
                WHEN (IdPlateforme = 1 AND IdSecteur = 4) then 3
                WHEN (IdPlateforme = 3 AND IdSecteur = 1) then 4
                WHEN (IdPlateforme = 3 AND IdSecteur = 2) then 5
                WHEN (IdPlateforme = 3 AND IdSecteur = 4) then 6
                WHEN (IdPlateforme = 2 AND IdSecteur = 1) then 7
                WHEN (IdPlateforme = 2 AND IdSecteur = 2) then 8
                WHEN (IdPlateforme = 2 AND IdSecteur = 4) then 9
            
            End
        
        WHERE IdPlateformeSecteur is NULL;  

this is what I'm coming up with:

if (projet.IdPlateforme == 1 && projet.IdSecteur == 1)
            {
                projet.IdPlateformeSecteur = 1;
            }
            else if (projet.IdPlateforme == 1 && projet.IdSecteur == 2)
            {
                projet.IdPlateformeSecteur = 2;
            }
            else if (projet.IdPlateforme == 1 && projet.IdSecteur == 4)
            {
                projet.IdPlateformeSecteur = 3;
            }
            else if (projet.IdPlateforme == 3 && projet.IdSecteur == 1)
            {
                projet.IdPlateformeSecteur = 4;
            }
            else if (projet.IdPlateforme == 3 && projet.IdSecteur == 2)
            {
                projet.IdPlateformeSecteur = 5;
            }
            else if (projet.IdPlateforme == 3 && projet.IdSecteur == 4)
            {
                projet.IdPlateformeSecteur = 6;
            }
            else if (projet.IdPlateforme == 2 && projet.IdSecteur == 1)
            {
                projet.IdPlateformeSecteur = 7;
            }
            else if (projet.IdPlateforme == 2 && projet.IdSecteur == 2)
            {
                projet.IdPlateformeSecteur = 8;
            }
            else if (projet.IdPlateforme == 2 && projet.IdSecteur == 4)
            {
                projet.IdPlateformeSecteur = 9;
            }

my search are giving me example with select but I dont have a select. It's working but I would like to do it the proper way. Thank you

As @gun2171 indicating there is nothing here in regards to LINQ .

For clarity of your current code seems easy enough to read and maintain. If working with C# 8 you could use a switch expression. Thinking eloquent , better to think of coming back to the code in days, months or years, do you and others understand this code?

Mocked class

public class ProjectItem
{
    public int IdPlateforme { get; set; }
    public int IdSecteur { get; set; }
    public int IdPlateformeSecteur { get; set; }
}

Method in a class named Operations.cs

private static int SetIdSecteur(ProjectItem sender) => sender.IdPlateforme switch
    {
        1 when sender.IdSecteur == 1 => 1,
        1 when sender.IdSecteur == 2 => 2,
        1 when sender.IdSecteur == 4 => 3,
        3 when sender.IdSecteur == 1 => 4,
        3 when sender.IdSecteur == 2 => 5,
        3 when sender.IdSecteur == 4 => 6,
        2 when sender.IdSecteur == 1 => 7,
        2 when sender.IdSecteur == 2 => 8,
        2 when sender.IdSecteur == 4 => 9,
        _ => sender.IdPlateformeSecteur
    };

Usage

var projet = new ProjectItem() { IdPlateforme = 1, IdPlateformeSecteur = 2};

projet.IdSecteur = SetIdSecteur(projet);

Edit

Happened to be chatting with a Microsoft PM on the Visual Studio team and they provided another idea via tuples using C# 8. I can't take credit for this yet seems prudent to present this alternate solution.

public static int SetIdSecteur3(ProjectItem sender)
    => (sender.IdPlateforme, sender.IdSecteur) switch
    {
        (1, 1) => 1,
        (1, 2) => 2,
        (1, 4) => 3,
        (3, 1) => 4,
        (3, 2) => 5,
        (3, 4) => 6,
        (2, 1) => 7,
        (2, 2) => 8,
        (2, 4) => 9,
        _ => sender.IdPlateformeSecteur
    };

I made some assumptions based off of your depotProjet.Projet model with the below class, but should be close enough to accomplish what you're wanting:

(Link to working DotNet Fiddle: https://dotnetfiddle.net/i2RAx3 )

You can use a Func<int, int, int> to pass in the IdPlatforme and IdSecteur to move the if statement out of your query (the below uses recursive pattern matching and requires C# 8.0 or greater, otherwise you can replace it with case statement):

Func<int, int, int> SetIdPlatformeSecteur = (p, s) =>
    {
        int r = (p, s) switch
        {

            _ when p == 1 && s == 1 => 1,
            _ when p == 1 && s == 2 => 2,
            _ when p == 1 && s == 4 => 3,
            _ when p == 3 && s == 1 => 4,
            _ when p == 3 && s == 2 => 5,
            _ when p == 3 && s == 4 => 6,
            _ when p == 2 && s == 1 => 7,
            _ when p == 2 && s == 2 => 8,
            _ when p == 2 && s == 4 => 9,
            _ => throw new ArgumentException(message: "Id combination not recognized", paramName: $"{p} {s}")

        };

        return r;
    };

Then you can query your Projects database and return an anonymous type that includes the fields from your Project model you added IdPlateformeSecteur like this:

new {
       x.Id, 
       x.IdPlateforme, 
       x.IdSecteur, 
       //...any other properties your model has and want returned
       IdPlateformeSecteur = SetIdPlatformeSecteur(x.IdPlateforme, x.IdSecteur)
    });

Full LINQPad example below:

// Demo data to represent what would be in your databaseContext.Projects
List<Project> Projects = 
                        new List<Project> {
                                new Project { Id = 1, IdPlateforme = 1, IdSecteur = 1},
                                new Project { Id = 2, IdPlateforme = 1, IdSecteur = 2},
                                new Project { Id = 3, IdPlateforme = 1, IdSecteur = 4},
                                new Project { Id = 4, IdPlateforme = 3, IdSecteur = 1},
                                new Project { Id = 5, IdPlateforme = 3, IdSecteur = 2},
                                new Project { Id = 6, IdPlateforme = 3, IdSecteur = 4},
                                new Project { Id = 7, IdPlateforme = 2, IdSecteur = 1},
                                new Project { Id = 8, IdPlateforme = 2, IdSecteur = 2},
                                new Project { Id = 9, IdPlateforme = 2, IdSecteur = 4},
                            };

void Main()
{           
                        
    var results = Projects.Select(x => new {x.Id, x.IdPlateforme, x.IdSecteur, IdPlateformeSecteur = SetIdPlatformeSecteur(x.IdPlateforme, x.IdSecteur)});
    
    results.Dump();
}

Func<int, int, int> SetIdPlatformeSecteur = (p, s) =>
    {
        int r = (p, s) switch
        {

            _ when p == 1 && s == 1 => 1,
            _ when p == 1 && s == 2 => 2,
            _ when p == 1 && s == 4 => 3,
            _ when p == 3 && s == 1 => 4,
            _ when p == 3 && s == 2 => 5,
            _ when p == 3 && s == 4 => 6,
            _ when p == 2 && s == 1 => 7,
            _ when p == 2 && s == 2 => 8,
            _ when p == 2 && s == 4 => 9,
            _ => throw new ArgumentException(message: "Id combination not recognized", paramName: $"{p} {s}")

        };

        return r;
    };

public class Project
{
    public int Id { get; set; }
    public int IdPlateforme { get; set; }
    public int IdSecteur  { get; set; }
}

                                     

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM