Dapper QueryMultiple Get the actual values from the DB - c#

The dataset return 4 data tables as resultset but all in object{string} type even though in the table it is of different data types like int.
var ds = new DataSet();
        return  var ds = WithConnection(c =>
            {
                var multi = c.QueryMultiple(sql: "StoredProcedureName",
                                             param: new { Project = projectID },
                                            commandType: CommandType.StoredProcedure);
                while (!multi.IsConsumed)
                {
                    var dt = ChngDataTable(multi.Read());
                    ds.Tables.Add(dt);
                }
                return ds;
            });
protected DataTable ChngDataTable(IEnumerable<dynamic> items)
        {
            var exisData= items.ToArray();
            var dt = new DataTable();
            if (exisData.Count() == 0) return dt;
               
            foreach (var key in ((IDictionary<string, object>)data[0]).Keys)
            {
              if(!dt.Columns.Contains(key))
 dt.Columns.Add(key);
            }
            foreach (var d in exisData)
            {
                dt.Rows.Add(((IDictionary<string, object>)d).Values.ToArray());
            }
            return dt;
        }`
           
Is there any easy way to get the values with the actual data type from the DB as I cannot use any properties
Please help!!!!

please, take a look on the https://dapper-tutorial.net/querymultiple example.
You can use parameterised version of the Read method in order to get the type of choice.
If I understand the idea correctly, you would like to get data in the form of DataTables, then change DataTables and then do something with them.
In this case I'd split the work into stages in order to benefit from statically typed C# language.
1) Retrieve a result from database
2) Map to the POCO objects (like it is done in the example above)
3) Change fields according to a business logic
4) Map objects back to DataTables (either custom code with Reflection or any nuget package of choice).

Related

Specflow Integration test with HttpClient

I'm trying to create some specflow tests and using a WebApplicationFactory and want to moq HttpClient calls with Moq.Contrib.HttpClient.
So when i call my client, it's not intiated well (doesn't match with the moq)
Any ideas?
Thanks
So i've 2 differents HttpClients
var httpMessageHandler1 = new Mock<HttpMessageHandler>();
httpMessageHandler1.SetupRequest(HttpMethod.Post, $"http://localhost/api/Method1");
var httpMessageHandler2 = new Mock<HttpMessageHandler>();
httpMessageHandler2
.SetupRequest(HttpMethod.Post, $"http://localhost/api/Method2")
.ReturnsResponse(JsonSerializer.Serialize(response), "application/json");
I inject them like this in the stepDefinition class :
var application = new WebFactory<Program>()
                .WithWebHostBuilder(builder =>
                {
                    builder.ConfigureServices(services =>
                    {
                        var serviceProvider = services.BuildServiceProvider();
                        services.AddMediatR(typeof(DeviceRequestModel));
                      services.AddHttpClient("Client1").ConfigurePrimaryHttpMessageHandler(() => httpMessageHandler1.Object);
                      services.AddHttpClient("Client2").ConfigurePrimaryHttpMessageHandler(() => httpMessageHandler2.Object);
                    });
              });
Here is my WebFactory :
internal class WebFactory<TStartup> : WebApplicationFactory<TStartup> where TStartup : class
    {
        protected override void ConfigureWebHost(IWebHostBuilder builder)
        {
            base.ConfigureWebHost(builder);
            builder.UseEnvironment(Environments.Development);
            builder.UseTestServer()
                   .ConfigureTestServices(
                        services =>
                        {
                            services.AddScoped<TStartup>();
                            // Remove existing IHttpClientFactory and HttpClient
                            var httpClientFactoryDescriptor = services.SingleOrDefault(d => d.ServiceType == typeof(IHttpClientFactory));
                            services.Remove(httpClientFactoryDescriptor);
                            var httpClientDescriptor = services.SingleOrDefault(d => d.ServiceType == typeof(HttpClient));
                            services.Remove(httpClientDescriptor);
                        });
        }
    }
In my Command, i get the IHttpClientFactory
public Handler(IHttpClientFactory factory)
{
this.client = factory.CreateClient("Client1");
}
So when i do the
HttpResponseMessage response = await this.client.PostAsync
I've got this exception 'System.InvalidOperationException' dans System.Net.Http.dll and my client is not intiated well (doesn't match with the moq)
So it's not my moq object from services.AddHttpClient("Client1").ConfigurePrimaryHttpMessageHandler(() => httpMessageHandler1.Object);

C# - Send a file in the body of an http request using RestRequest

I tried sending an xlsx file (from path) in the body of a POST http request.
I was able to send the file but it arrived as a corrupted file.(I have no way to try to check what's the issue on the api, because it's a api like Amazon etc.)
this is the code I tried:
public async Task<string> PostPostman()
    {
         try
            {
                string filePath = #"D:\example2.xlsx";
FileStream fs = File.OpenRead(filePath);
var streamContent = new StreamContent(fs);
streamContent.Headers.Add("Content-Type", "application/xlsx");
                var client = new RestClient("https://api.xxx.com/v1/FileUpload");
                var request = new RestRequest(Method.Post.ToString());
                request.Method = Method.Post;
                request.AddHeader("Content-Type", "application/xlsx");
                request.AddHeader("Authorization", "Bearer xxxxxxxxxxxxx");
                request.AddParameter("application/xlsx", streamContent.ReadAsStringAsync().Result, ParameterType.RequestBody);
                RestResponse response = client.Execute(request);
                Console.WriteLine(response.Content);
                return response.Content;
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
                return ex.Message;
            }
        }
I found the issue was that ReadAsStringAsync() opened the file but didn't close it.
The solution I found is to send the file with File.ReadAllBytes(filePath) which reads the file and closes it back.
This is the final code:
public async Task<string> PostPostman()//found the code from the postman request I sent
        {
            try
            {
                string filePath = #"D:\example2.xlsx";
                var client = new RestClient("https://api.xxx.com/v1/FileUpload");
                var request = new RestRequest(Method.Post.ToString());
                request.Method = Method.Post;
                request.AddHeader("Content-Type", "application/xlsx");
                request.AddHeader("Authorization", "Bearer xxxxxxxxxxxxx");
                request.AddParameter("application/xlsx", File.ReadAllBytes(filePath), ParameterType.RequestBody);
                RestResponse response = client.Execute(request);
                Console.WriteLine(response.Content);
                return response.Content;
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
                return ex.Message;
            }
        }

Unity Vector2.MoveTowards function is not working

Currently, I am making a board game with Unity. The player has to be moved according to the results of rolling dice, but the player always moves one space less in the first turn.
I checked that the dice was thrown well and the results were delivered well, but the player moves one space less, only in the first turn. (For example, assume that you throw the dice for the first turn and get 2, you don't move two spaces, but only one space.)
I put a script called FollowThePath in each player object (soju, beer, whiskey, cocktail), and decide player's order with the GameController.
In addition, waypoints were placed in each board game compartment managed in an array called waypoints. It is the principle of moving by stepping on each waypoint according to the result of throwing dice.
I'll attach the code.help me please.....
blue dots are waypoints. and the object on bottom right is the player.
FollowThePath.cs
private void Start()
    {
        transform.position = waypoints[wayPointIndex].transform.position;
        howManyMove = 0;
    }
    private void Update()
    {
        if (moveAllowed)
        {
            Move();
        }
    }
    private void Move()
    {
        if (wayPointIndex <= waypoints.Length - 1)
        {
           
            if (howManyMove < GameControl.yutSideThrown && transform.position == waypoints[wayPointIndex].transform.position)
            {
                isReallyMove = false;
               
                if (wayPointIndex == 5)
                    wayPointIndex += 15;
                else if (wayPointIndex == 10)
                    wayPointIndex += 15;
                else if (wayPointIndex == 22)
                    wayPointIndex += 6;
                else if (wayPointIndex == 27)
                    wayPointIndex -= 4;
                else if (wayPointIndex == 24)
                    wayPointIndex -= 9;
                else wayPointIndex += 1;
                //말을 실제로 몇번 움직였는지 나타내는 변수
                howManyMove += 1;
                
            }
            
            transform.position = Vector2.MoveTowards(transform.position, waypoints[wayPointIndex].transform.position, moveSpeed * Time.deltaTime);
            
            if (transform.position == waypoints[wayPointIndex].transform.position)
            {
               
                Debug.Log("Moved");
            }
            isReallyMove = true;
        
        }
    }
}
GameControl.cs
void Start()
    {   
        //각 player 변수에 object들 연결하는 코드
        player1 = GameObject.Find("soju");
        player2 = GameObject.Find("beer");
        player3 = GameObject.Find("whiskey");
        player4 = GameObject.Find("cocktail");
        //자기 차례에 moveAllowed가 true가 되어야함. 그래서 초기화는 false로
        player1.GetComponent<FollowThePath>().moveAllowed = false;
        player2.GetComponent<FollowThePath>().moveAllowed = false;
        player3.GetComponent<FollowThePath>().moveAllowed = false;
        player4.GetComponent<FollowThePath>().moveAllowed = false;
        whoWinsText.text = "";
        whosTurn.text = "소주 팀 차례!";
    }
    
    // Update is called once per frame
    void Update()
    {
        
        if(player1.GetComponent<FollowThePath>().howManyMove >= yutSideThrown && player1.GetComponent<FollowThePath>().isReallyMove)
        {
            whosTurn.text = "맥주 팀 차례!";
            player1.GetComponent<FollowThePath>().howManyMove = 0;
            player1.GetComponent<FollowThePath>().moveAllowed = false;
        }
...
please help me!TT

ElasticSearch find indexed objects with distinct nested list elements from specified terms

Let's suppose we have a student with a (nested) list of scores as follows:
public class Student
{
public string FullName { get; set; }
public List<Score> Scores { get; set; } = new List<int>();
}
public class Score
{
public int Value { get; set; }
}
How do I write an ElasticSearch query using NEST (or simple query) to get all students who have at least 2 different scores from 7 to 10.
Thus for example, if a student got scores {2,7,10} or {8,10}, he should be in our result, whereas a student with {10, 6, 5} or {8, 8} or {2, 7} should not get in our result.
What I have come up with is:
GET /index/student/_search
{
"query": {
"nested": {
"path": "scores",
"query": {
"bool": {
"should":
[
{
"bool": {
"filter": [
{
"terms": {
"scores.value": [7, 10]
}
},
{
"terms":{
"scores.value": [8, 9]
}
}
]
}
},
{
"bool": {
"filter": [
{
"terms": {
"scores.value": [7, 8]
}
},
{
"terms":{
"scores.value": [9, 10]
}
}
]
}
}
]
}
}
}
}
}
But ElasticSearch does not seem to allow conjunctions of TERMS queries (returning 0 hits). And even if it did work, I would still require something more elegant, because in case we have more than 4 allowed values, this would become a pain.
UPDATE
I've tried the following script, but got 0 results as well:
GET /index/student/_search
{
"query": {
"nested": {
"path": "scores",
"query": {
"bool": {
"filter": [
{
"exists": {
"field": "scores"
}
},
{
"script": {
"script": """
              boolean condition = false;
              def availableScores = [7, 8, 9, 10];
              def scores = doc['scores.id'].values;
             
              for (int i = 0; i < scores.length; i++)
              for(int j = 0; j < availableScores.length; j++)
              if (scores[i] == availableScores[j])
              {
              if (condition == true)
              return (true);
             
              condition = true;
              availableScores.remove(j);
              break;
              }
              return (false)"""
}
}
]
}
}
}
}
}
After a long while, I have found a query that works:
GET /index/student/_search
{
  "query": {
    "bool": {
      "should": [
        {
          "bool": {
            "must": [
              {
                "nested": {
                  "path": "scores",
                  "query": {
                    "terms": {
                      "scores.value": [
                        7,
                        10
                      ]
                    }
                  }
                }
              },
              {
                "nested": {
                  "path": "scores",
                  "query": {
                    "terms": {
                      "scores.value": [
                        8,
                        9
                      ]
                    }
                  }
                }
              }
            ]
          }
        },
        {
        "bool": {
            "must": [
              {
                "nested": {
                  "path": "scores",
                  "query": {
                    "terms": {
                      "scores.value": [
                        7,
                        9
                      ]
                    }
                  }
                }
              },
              {
                "nested": {
                  "path": "scores",
                  "query": {
                    "terms": {
                      "scores.value": [
                        8,
                        10
                      ]
                    }
                  }
                }
              }
            ]
          }
        }
      ]
    }
  }
}
The trick here was separating 1 nested query into multiple ones and putting them inside a should query.
I would still like a more elegant solution (through a script, I guess), but for now, I'll leave it as the final answer.

How I can order by descending and then take some items using linq?

I have the following C# LINQ code :
List<myProductList> qMain = (
from m in db.ProductsList.OrderByDescending
(it => it.GroupCode == 1 || it.L1 == 1)
where m.GoodCode == 1 || m.L1 == 1
select new myProductList
{
StackAmount = m.StackAmount,
GoodCode = m.GoodCode,
PrivateCodeForSort = m.PrivateCodeForSort,
GoodMainCode = m.GoodMainCode,
MaxSellPrice = m.MaxSellPrice,
SellPrice5 = m.SellPrice5,
SellPriceType = m.SellPriceType,
GoodExplain1 = m.GoodExplain1,
Writer = m.Writer,
DragoMan = m.DragoMan,
GoodName = m.GoodName,
Printing = m.Printing,
CoverType = m.CoverType,
PrintYear = m.PrintYear,
PrintPeriod = m.PrintPeriod,
Creation = m.CreationDate
}).Take(50).ToList();
I have a kind of serious problem, The ProductList table is a very big and I don't want to transfer all rows from my database server so I solve this problem by taking 50 rows which is my necessary but the problem is I want to order by descending first of all and then take 50 rows but this code first take 50 rows by ascending and then order by decending only those 50 rows that has already transferred and sorted. how I can fix this ?
No, the code you've given:
Orders the results
Filters the results
Projects the results
Limits the results to 50
... in that order.
On the other hand, it's a slightly odd OrderByDescending call to start with. If you want a different ordering applied as well you could easily do that too - for example:
from m in db.ProductsList
orderby (it.GroupCode == 1 || it.L1 == 1) descending, it.SellPrice5 descending
where m.GoodCode == 1 || m.L1 == 1
select new myProductList
... // code as before
Something like this:
List<myProductList> qMain = (
                         from m in db.ProductsList.OrderByDescending(it => it.GroupCode == 1 || it.L1 == 1)
                         where m.GoodCode == 1 || m.L1 == 1                                                                                            
                         select new myProductList
                         {
                             StackAmount = m.StackAmount,
                             GoodCode = m.GoodCode,
                             PrivateCodeForSort = m.PrivateCodeForSort,
                             GoodMainCode = m.GoodMainCode,
                             MaxSellPrice = m.MaxSellPrice,
                             SellPrice5 = m.SellPrice5,
                             SellPriceType = m.SellPriceType,
                             GoodExplain1 = m.GoodExplain1,
                             Writer = m.Writer,
                             DragoMan = m.DragoMan,
                             GoodName = m.GoodName,
                             Printing = m.Printing,
                             CoverType = m.CoverType,
                             PrintYear = m.PrintYear,
                             PrintPeriod = m.PrintPeriod,
                             Creation = m.CreationDate
                         }).OrderByDescending(m=>m.GoodName).Take(50).ToList();
It won't bring the entire dataset; you can look at the generated SQL query to confirm.

Categories

Resources