Search code examples
c#sql-serverentity-framework-corelinq-to-entities

How to convert SQL query values separated comma to list by using entity framework core 7?


I work on asp.net core razor page . I face issue How to convert complicated sql query to entity framework core 7

Exactly I need to convert this SQL statement to LINQ to entity without write SQL statement on csharp meaning i need to use code first entity framework core 7

function below get values separated comma and convert it to list based on related Print server .

 public DataTable GetBranchesRelatedToServer(string PrintServer)
        {
               DataTable dt = new DataTable();
                
                cmd.CommandText = ";with cte as (SELECT distinct PrintServer,REPLACE (Split.A.value('.', 'VARCHAR(4000)') , ' ', '' ) as BranchId FROM  (SELECT BranchCode, PrintServer,CAST ('<M>' + REPLACE(BranchCode, ',', '</M><M>') + '</M>' AS XML) AS String   FROM  [dbo].[tbl_branchPDFexe]) AS A CROSS APPLY String.nodes ('/M') AS Split(A)) select t.PrintServer,t.BranchId,b.vBranchDesc from  cte t inner join [dbo].[tbl_Branch] b with(nolock) on t.BranchId=b.iBranchCode and PrintServer=@PrintServer";
                
            
            return dt;
        }

when models used is

[Table("tbl_branchPDFexe")]
    public class BranchPDFexe
    {
       public decimal Id { get; set; }
       public string BranchCode { get; set; }
       public string PrintServer { get; set; }
    }

[Table("tbl_Branch")]
    public class Branch
    {
        [Key]
        public string iBranchCode { get; set; }
        public string vBranchDesc { get; set; }

    }

Data input before query run on table tbl_branchPDFexe

input before split

Table structure tbl_Branch

branches table

Expected result will be

result after split

so code will be after convert it to entity framework core

 public list GetBranchesRelatedToServer(string PrintServer)
            {
dbcontext.BranchPDFexe.where().join(branch)
// so How to make it by linq to entity 
                   return list
            }

updated post

as you say .NET core 7 don't support CTE with xml

can you show to me available ways can do it by using entity framework core 7

updated post can you please help me to apply this logic

1-return list of BranchCode without comma separated from table BranchPDFexe

2-join with table Branch to get branchName so no need to depend on sql

So How to do these steps please

Update Post

can you please help me to solve issue without using sql query as below

var distinctBranchCodesAndPrintServers = _adc.BranchPDFexe
     .SelectMany(b => b.BranchCode.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries)
         .Select(bc => new { BranchCode = bc.Trim(), b.PrintServer }));

but i get error

System.InvalidOperationException: 'The LINQ expression 'b => b.BranchCode.Split(
separator: char[] { , },
options: RemoveEmptyEntries)
.AsQueryable()
     .Distinct()
     .ToList();

Update Post

sql statment

cmd.CommandText = ";with cte as (SELECT distinct PrintServer,REPLACE (Split.A.value('.', 'VARCHAR(4000)') , ' ', '' ) as BranchId FROM  (SELECT BranchCode, PrintServer,CAST ('<M>' + REPLACE(BranchCode, ',', '</M><M>') + '</M>' AS XML) AS String   FROM  [dbo].[tbl_branchPDFexe]) AS A CROSS APPLY String.nodes ('/M') AS Split(A)) select t.PrintServer,t.BranchId,b.vBranchDesc from  cte t inner join [dbo].[tbl_Branch] b with(nolock) on t.BranchId=b.iBranchCode and PrintServer=@PrintServer";

statement above split branch code from table BranchPDFexe to list of

numbers then join with table tbl_branches to get VBranchDesc

so BranchCode have 10206,10207,101lc01 for print server 10 will be

10206   10
10207   10
101lc01 10

and after that join with table tbl_branches to get vbranchDesc so it will be

10206    Jumira           10  
10207    Al Aweer         10
101lc01  MalCamp- Alquoz  10

so final Statement will be

PrinterServer iBranchCode VBranchDesc

Solution

  • I'll preface by saying: your database design is fundamentally broken. You should normalize the table out into separate rows..


    You can use STRING_SPLIT in a raw query to get an IQueryable<string>, which you can then compose over to get the rest of the joins.

    public static IQueryable<string> GetSplitBranchPdf(this YourDbContext db, string printServer)
    {
        return db.Database.SqlQueryRaw<string>(@"
    SELECT
      TRIM(v.value) AS Value
    FROM dbo.tbl_branchPDFexe bpd
    CROSS APPLY STRING_SPLIT(bpd.BranchCode, ',') v
    WHERE bpd.PrintServer = @PrintServer
    ",
            new SqlParameter("@PrintServer", SqlDbType.NVarChar, 100) { Value = printServer }
        );
    }
    
    public async Task<List<MyResult>> GetBranchesRelatedToServer(string printServer)
    {
        var splitBranches = Db.GetSplitBranchPdf(printServer);
        // must do this in a separate step, do not merge
        var results =
            from b in Db.Branch
            join t in splitBranches
              on t equals b.iBranchCode
            select new MyResult {
                PrintServer = printServer,
                BranchId = t.BranchId,
                vBranchDesc = b.vBranchDesc
            };
        return results.ToListAsync();
    }
    

    For raw queries returning a single scalar column we can use db.Database.SqlQueryRaw, and the column name must be Value. Otherwise we need to use a full entity with db.Set<SomeEntity>.FromSqlRaw.

    Note that the first function returns an IQueryable. It does not run any anything until it's actually queried, which means it is composable.