I have a dynamic rule engine and i want to pass class to this and each time the class is sent differently.
For example:
Order MyOrder = new Order()
{
OrderId = 1,
Customer = new Customer()
{
FirstName = "John",
LastName = "Doe",
Country = new Country()
{
CountryCode = "AUS"
}
},
Items = new List<Item>(){
new Item(){ ItemCode = "MM23", Cost=5.25M},
new Item(){ ItemCode = "LD45", Cost=5.25M},
new Item(){ ItemCode = "Test", Cost=3.33M},
}
};
I want to change this:
var compiledRule = engine.CompileRule<Order>(rule);
to :
dynamic obj = MyOrder;
var compiledRule = engine.CompileRule<?????>(rule);
how can I get Type of obj and put instead of "????"
I found solution after search a lot
var engine = new MRE();
var compiledRule = engine.CompileRule<Order>(rule);
change to:
var engine = new MRE();
var compiledRule = typeof(MRE).GetMethod("CompileRule").MakeGenericMethod(myOrder.GetType())
.Invoke(engine, new object[] { rule}) as dynamic;
Related
I am trying to generate a list result through linq.
I would like to have a result as a list with unique folder id with 0th item as folder_name, 1st Item as a list with one or more projects having fields project_id,name and description.
I have written following query:
Folders is basically model with format as folderid, name, List projects where Project Model has project_id, name and description
from the following records:
Models
public class FolderModel
{
public int folder_id { get; set; }
public string folder_name { get; set; }
public List<ProjectModel> projects{ get; set; }
}
public class ProjectModel
{
public int project_id { get; set; }
public string project_name { get; set; }
public string project_description { get; set; }
}
public class ResultModel
{
public List<FolderModel> folders { get; set; }
}
Result Data
List<FolderModel, List<ProjectModel>> result = new List<FolderModel, List<ProjectModel>>();
List<ProjectModel> projectList1 = new List<>();
ProjectModel projectModel1 = new ProjectModel();
projectModel1.project_name = "F1P1";
projectModel1.project_description = "F1P1";
projectList1.add(projectModel1);
List<ProjectModel> projectList2 = new List<>();
ProjectModel projectModel21 = new ProjectModel();
projectModel21.project_name = "F2P1";
projectModel21.project_description = "F2P1";
projectList2.add(projectModel21);
ProjectModel projectModel22 = new ProjectModel();
projectModel22.project_name = "F2P2";
projectModel22.project_description = "F2P2";
projectList2.add(projectModel22);
List<ProjectModel> projectList3 = new List<>();
ProjectModel projectModel3 = new ProjectModel();
projectModel3.project_name = "F3P1";
projectModel3.project_description = "F1P3";
projectList3.add(projectModel3);
ResultModel resultModel = new resultModel();
resultModel.(new FolderModel { folder_id: 1,folder-name: "F1" }, projectList1);
FolderModel folderModel1 = new FolderModel();
folderModel1.folder_id = 1
folderModel1.folder_name = "F1"
folderModel1.projects = projectList1
FolderModel folderModel2 = new FolderModel();
folderModel2.folder_id = 2
folderModel2.folder_name = "F2"
folderModel2.projects = projectList2
FolderModel folderModel3 = new FolderModel();
folderModel3.folder_id = 3
folderModel3.folder_name = "F3"
folderModel3.projects = projectList3
ResultModel resultModel = new ResultModel();
List<FolderModel> folderList = new List<>();
folderList.add(folderModel1);
folderList.add(folderModel2);
folderList.add(folderModel3);
resultModel.folders = folderList
SQL Data
folder_id | folder_name | project_id | project_name | project_description
1 F1 11 F1P1 F1P1
2 F2 21 F2P1 F2P1
2 F2 22 F2P2 F2P2
3 F3 31 F3P1 F3P1
4 F4 41 F4P1 F4P1
5 F5 51 F5P1 F5P1
This is what I have tried
var result = resultModel.folders.GroupBy(x => new { x.folder_id }).ToList();
I am sure that after group by I have to select name but not sure how can I generate project into a list and add it to main folder id. Can someone please guide on this.
You can query like this:
var result =
resultModel
.folders
.GroupBy(x => new { x.folder_id })
.Select(s => new
{
folder_id = s.Key,
folder_name = s.First().folder_name
})
.ToList();
It seems to me that you're looking for this:
var folders = new []
{
new { folder_id = 1, folder_name = "F1", project_id = 11, project_name = "F1P1", project_description = "F1P1" },
new { folder_id = 2, folder_name = "F2", project_id = 21, project_name = "F2P1", project_description = "F2P1" },
new { folder_id = 2, folder_name = "F2", project_id = 22, project_name = "F2P2", project_description = "F2P2" },
new { folder_id = 3, folder_name = "F3", project_id = 31, project_name = "F3P1", project_description = "F3P1" },
new { folder_id = 4, folder_name = "F4", project_id = 41, project_name = "F4P1", project_description = "F4P1" },
new { folder_id = 5, folder_name = "F5", project_id = 51, project_name = "F5P1", project_description = "F5P1" },
};
List<FolderModel> result =
folders
.GroupBy(
x => new { x.folder_id, x.folder_name },
x => new { x.project_id, x.project_name, x.project_description })
.Select(x => new FolderModel()
{
folder_id = x.Key.folder_id,
folder_name = x.Key.folder_name,
projects = x.Select(y => new ProjectModel()
{
project_id = y.project_id,
project_name = y.project_name,
project_description = y.project_description,
}).ToList(),
})
.ToList();
I am trying to use AWS SDK for .NET Core.
Create a table to count views on videos.
Add a view count for a day.
Increment existing count for a day.
Query for video counts between two dates for a video.
.NET Core AWS SDK uses Async methods which are not documented in AWS. There is a feature request on their github page for this to happen.... but it is dated from last year. (https://github.com/aws/aws-sdk-net/issues/787)
CREATE THE TABLE
This works and creates a table on the AWS Console.
var ctRequest = new CreateTableRequest
{
AttributeDefinitions = new List<AttributeDefinition>()
{
new AttributeDefinition
{
AttributeName = "ViewUid",
AttributeType = ScalarAttributeType.S
},
new AttributeDefinition
{
AttributeName = "ViewDate",
AttributeType = ScalarAttributeType.S
}
},
KeySchema = new List<KeySchemaElement>
{
new KeySchemaElement
{
AttributeName = "ViewUid",
KeyType = KeyType.HASH //Partition key
},
new KeySchemaElement
{
AttributeName = "ViewDate",
KeyType = KeyType.RANGE
}
},
ProvisionedThroughput = new ProvisionedThroughput
{
ReadCapacityUnits = 5,
WriteCapacityUnits = 6
},
TableName = _settings.AWSDynamoDBViewCountTable
};
var response = _client.CreateTableAsync(ctRequest).Result;
UPDATE AND ITEM WITH AUTO-INCREMENT A FIELD
This, sadly, is where i hit issues. The old docs are found here under the Atomic Counter section. (https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/LowLevelDotNetItemCRUD.html)
Invalid ConditionExpression: Syntax error; token: \"SET\", near: \"SET
VC\"
var viewData = new Document();
viewData["ViewUid"] = videoUid; //Table entry UID
viewData["VideoId"] = videoId; // Video ID
viewData["ViewDate"] = date;
viewData["ViewCount"] = 0;
//Document result = await _viewCountTable.PutItemAsync(viewData);
Expression expr = new Expression();
expr.ExpressionStatement = "SET #VC = #VC + :val";
expr.ExpressionAttributeValues[":val"] = 1;
expr.ExpressionAttributeNames["#VC"] = "ViewCount";
var updateConfig = new UpdateItemOperationConfig() {
ConditionalExpression = expr,
ReturnValues = ReturnValues.UpdatedNewAttributes
};
var result = await _viewCountTable.UpdateItemAsync(viewData, updateConfig);
return result;
QUERY FOR DATE RANGE
Get one video's view count for a date range.
string queryTimeSpanStartString = dateFrom.ToString(AWSSDKUtils.ISO8601DateFormat);
string queryTimeSpanEndString = dateTo.ToString(AWSSDKUtils.ISO8601DateFormat);
var request = new QueryRequest
{
TableName = _settings.AWSDynamoDBViewCountTable,
KeyConditions = new Dictionary<string, Condition>()
{
{
"VideoId", new Condition()
{
ComparisonOperator = "EQ",
AttributeValueList = new List<AttributeValue>()
{
new AttributeValue { S = videoId }
}
}
},
{
"ViewDate",
new Condition
{
ComparisonOperator = "BETWEEN",
AttributeValueList = new List<AttributeValue>()
{
new AttributeValue { S = queryTimeSpanStartString },
new AttributeValue { S = queryTimeSpanEndString }
}
}
}
}
};
var response = await _client.QueryAsync(request);
Any help would be appreciated.
I was able to update the ViewCount with the following code:
string tableName = "videos";
var request = new UpdateItemRequest
{
Key = new Dictionary<string, AttributeValue>() { { "ViewUid", new AttributeValue { S = "replaceVideoIdhere" } } },
ExpressionAttributeNames = new Dictionary<string, string>()
{
{"#Q", "ViewCount"}
},
ExpressionAttributeValues = new Dictionary<string, AttributeValue>()
{
{":incr", new AttributeValue {N = "1"}}
},
UpdateExpression = "SET #Q = #Q + :incr",
TableName = tableName
};
var response = await _dynamoDbClient.UpdateItemAsync(request);
I created a table called "videos" with a partition key named "ViewUid" as string. Let me know if this works for you.
public class Emp
{
public int EmpId { get; set; }
public string Type { get; set; }
public List<string> Email { get; set; }
}
I fetch data from database and put it in a list
List<Emp> employees= new List<Emp>();
// fill the list here via DB call
The list would have, please also note that Type field would always be same for same user but email would be different
employees[0] = new Emp{ EmpId = 1, Type = "User", Email = "one#test.com" };
employees[1] = new Emp{ EmpId = 1, Type= "User", Email = "two#test.com" };
employees[2] = new Emp{ EmpId = 2, Type = "Test", Email = "three#test.com" };
employees[3] = new Emp{ EmpId = 2, Type= "Test", Email = "four#test.com"};
employees[4] = new Emp{ EmpId = 3, Type = "Test", Email = "five#test.com" };
employees[5] = new Emp{ EmpId = 3, Type= "Test", Email = "six#test.com"};
employees[6] = new Emp{ EmpId = 4, Type= "User", Email = "seven#test.com"};
I'm trying to group Emp based on their EmpId
so the result should be a new list
Expected Result
Result = new Emp{ EmpId = 1, Type = "User", Email = "one#test.com", "two#test.com" };
new Emp{ EmpId = 2, Type = "Test", Email = "three#test.com", "four#test.com" };
new Emp{ EmpId = 3, Type = "Test", Email = "five#test.com", "six#test.com" };
new Emp{ EmpId = 4, Type = "User", Email = ""seven#test.com" };
//This is what I have done so far
// Please let me know if this is incorrect
var result = from emp in employees
group emp.Email by new { emp.EmpId, emp.Type } into g
select new { Key = g.Key, Type = g.Key.Type, Emails = g.ToList() };
// My problem comes here when I loop this result
foreach (var r in result)
{
Console.WriteLine(r.Key.EmpId + "--" + r.Key.Type);
//This is where I need to get all emails of the Employee which I grouped
// iF I IMPLEMENT FOREACH
foreach (var e in r.Emails)
{
//?? WHAT i DO HERE
//e.?? to get email
}
// OR iF I IMPLEMENT FOR LOOP
for(int i = 0 ; i< r.Emails.Count; i++)
{
Console.WriteLine("Inner Loop" + "--" + r.Key.EmpId + "--" + r.Key.Type + "--" + r.Emails[0].ToString()); // r.Emails[0].ToString() prints out System.Collections.Generic.List '1[System.String]
}
}
Please let me know if I mad eany mistake or there's other way to do this.
All I need is Group employees based on EmpID and also have their Type but grouped Emails.
Your group emp.Email by new { emp.EmpId, emp.Type } means that each element of the group will have a key of the anonymous type, and an "element type" of List<string>. You're then propagating that element type using Emails = g.ToList() in your select clause. Therefore I'd expect the type of r.Emails to be List<List<string>> (which you should be able to validate in Visual Studio by hovering over r.Emails.
You could handle that in your loop - or you could just flatten it in your select call, creating a new Emp:
select new Emp {
EmpId = g.Key.EmpId,
Type = g.Key.Type,
Emails = g.SelectMany(x => x).ToList()
};
Here the SelectMany call is just flattening the "sequence of lists" to a single sequence.
Maybe a slight change could be usefull: if you change the Email property from a list to string you could group the employees like that:
// Group by EmpId
var group = employees.GroupBy(e => e.EmpId);
and get the list for a single emp like this:
// Example get email List of first emp
group.First().Select(g => g.Email);
You could change your Emp class so that EMail is a string instead of a List<string>.
The foreach loop then becomes
foreach(string e in r.EMails){
//e holds the EMail
//do stuff
}
Try This:-
var query1 = from emp in employees
group emp.Email by new { emp.EmpId, emp.Type } into empgroup
select new
{
UserId = empgroup.Key.EmpId,
EmployeeType = empgroup.Key.Type,
EmaiIds = empgroup.SelectMany(x => x)
};
foreach (var x in query1)
{
Console.WriteLine(x.UserId);
Console.WriteLine(x.EmployeeType);
foreach (var emails in x.EmaiIds)
{
Console.WriteLine(emails);
}
}
void Main()
{
List<Emp> employees= new List<Emp>();
employees.Add(new Emp{ EmpId = 1, Type = "User", Email = "one#test.com" });
employees.Add(new Emp{ EmpId = 1, Type = "User", Email = "two#test.com" });
employees.Add(new Emp{ EmpId = 2, Type = "Test", Email = "three#test.com" });
employees.Add(new Emp{ EmpId = 2, Type = "Test", Email = "four#test.com" });
employees.Add(new Emp{ EmpId = 3, Type = "Test", Email = "five#test.com" });
employees.Add(new Emp{ EmpId = 3, Type = "Test", Email = "six#test.com" });
employees.Add(new Emp{ EmpId = 4, Type = "User", Email = "seven#test.com" });
var groupedList = from emp in employees
group emp.Email by new { emp.EmpId, emp.Type } into g
select new { Key = g.Key, Type = g.Key.Type, Emails = g.ToList() };
foreach (var result in groupedList)
{
//I'm using LINQPad to output the results
result.Key.EmpId.Dump();
foreach(var email in result.Emails)
{
email.Dump();
}
}
}
public class Emp
{
public int EmpId { get; set; }
public string Type { get; set; }
public string Email { get; set; }
}
My results are:
or...
void Main()
{
List<Emp> employees= new List<Emp>();
employees.Add(new Emp{ EmpId = 1, Type = "User", Emails = new List<string>(){"one#test.com"} });
employees.Add(new Emp{ EmpId = 1, Type = "User", Emails = new List<string>(){"two#test.com"} });
employees.Add(new Emp{ EmpId = 2, Type = "Test", Emails = new List<string>(){"three#test.com"} });
employees.Add(new Emp{ EmpId = 2, Type = "Test", Emails = new List<string>(){"four#test.com"} });
employees.Add(new Emp{ EmpId = 3, Type = "Test", Emails = new List<string>(){"five#test.com"} });
employees.Add(new Emp{ EmpId = 3, Type = "Test", Emails = new List<string>(){"six#test.com"} });
employees.Add(new Emp{ EmpId = 4, Type = "User", Emails = new List<string>(){"seven#test.com"} });
var groupedList = from emp in employees
group emp.Emails by new { emp.EmpId, emp.Type } into g
select new Emp {
EmpId = g.Key.EmpId,
Type = g.Key.Type,
Emails = g.SelectMany(x => x).ToList()
};
foreach (var result in groupedList)
{ //I'm using LINQPad to output
result.EmpId.Dump();
result.Emails.ForEach(e => e.Dump());
}
}
public class Emp
{
public int EmpId { get; set; }
public string Type { get; set; }
public List<string> Emails { get; set; }
}
My results are also:
I have an array of days (mon, tue, etc..) that I might not want to show, so when I create a list of days, if they are already in the "hiddendays", it doesn't add them.
// This would return for example 1, 2
var hDays = account.ScheduleHiddenDays.Split(',').Select(int.Parse).ToList();
var daySunday = new ViewModels.Day()
{
Id = 0,
Name = "Sunday"
};
var dayMonday = new ViewModels.Day()
{
Id = 1,
Name = "Monday"
};
var dayTuesday = new ViewModels.Day()
{
Id = 2,
Name = "Tueday"
};
var dayWednesday = new ViewModels.Day()
{
Id = 3,
Name = "Wednesday"
};
var dayThursday = new ViewModels.Day()
{
Id = 4,
Name = "Thursday"
};
var dayFriday = new ViewModels.Day()
{
Id = 5,
Name = "Friday"
};
var daySaturday = new ViewModels.Day()
{
Id = 6,
Name = "Saturday"
};
// This is where I need to check if they exist in hDays, it doesn't add them to this list. But how?
model.ScheduleHiddenDays = new List<ViewModels.Day>()
{
daySunday,
dayMonday,
dayTuesday,
dayWednesday,
dayThursday,
dayFriday,
daySaturday
};
Something along the lines of this:
var days = new List<ViewModels.Day>()
{
daySunday,
dayMonday,
dayTuesday,
dayWednesday,
dayThursday,
dayFriday,
daySaturday
};
model.ScheduleHiddenDays = days.Where(x => !hDays.Contains(x.Id)).ToList();
Is there a more elegant/concise way of this; I'd like to get rid of foreach loop with the WorkListItem initialization code.
var queryable = registrations.Select(
r => new
{
r.Id, r.AccountNumber, r.DateAdded, r.DateUpdated, r.Patient, r.Patient.InsuranceInfos
});
var list = queryable.ToList();
var workListItems = new List<WorkListItem>();
foreach (var anonymous in list)
{
var w = new WorkListItem
{
Id = anonymous.Id,
ClientAccountId = anonymous.AccountNumber,
DateAdded = anonymous.DateAdded,
DateUpdated = anonymous.DateUpdated,
Patient = anonymous.Patient,
InsuraceInfos = anonymous.Patient.InsuranceInfos
};
workListItems.Add(w);
}
return workListItems;
Yes you can completely cut out the "middle-man" as it were and select straight into a new WorkListItem as below:
var list = registrations.Select(r => new WorkListItem
{
Id = r.Id,
ClientAccountId = r.AccountNumber,
DateAdded = r.DateAdded,
DateUpdated = r.DateUpdated,
Patient = r.Patient,
InsuraceInfos = r.Patient.InsuranceInfos
}).ToList();