c# how to get name based on enum - c#

Here I have small table Like Employee
EmpId EmpName EmpType
1 John 1
2 Mick 3
3 Smith 2
I wrote a simple Linq query finding details Like
public Users GetUsers(int Id)
{ var x = from n in db.Users
where n.Username == Id
select n;
return x.FirstOrDefault();
}
when its get result as EmpId=1,EmpName=John,Emptype=1 Insted of 1 i need Admin from enum
enum TypeofEmp{
Admin=1,
HttpRequest=2,
Devoloper=3
};
How can i get these values

You can use Enum.GetName method:
Enum.GetName( typeof( TypeofEmp ), value );
Also, if you want to convert an int value to instance of your enum, you can do simple cast, for example:
var enumInstance = ( TypeofEmp )1;

Enum.GetValues returns an array of all values;
foreach(var value in Enum.GetValues(typeof(TypeofEmp)))
{
Console.WriteLine($"{(TypeofEmp)value} (integer value: {(int)value})");
}
// output:
Admin (integer value: 1)
HttpRequest (integer value: 2)
Devoloper (integer value: 3)

Related

Find Common value against different id c# Linq

I have one table which is looking like this
ID
UserID
UserEncryptValue
1
1
abcd
2
2
1234
3
3
qwert
4
1
rstuv (Common value for user 1 and 2)
5
2
rstuv (Common value for user 1 and 2)
6
2
78901 (Common value for user 2 and 3)
7
3
78901 (Common value for user 2 and 3)
8
1
Hello123 (Common value for user 1,2 and 3)
9
2
Hello123 (Common value for user 1,2 and 3)
10
3
Hello123 (Common value for user 1,2 and 3)
Now I want to find if user 1 and 2 or 1, 2 and 3 have common value or not with use of Linq.
Assuming you're mapping that table to an actual object like 'UserData' like this:
public class UserData
{
public int Id { get; set; }
public int UserId { get; set; }
public string UserEncryptValue { get; set; }
}
You can get the common values like this (userData is a list of UserData and represents your data):
var searchId = 1;
var commonValues = userData.GroupBy(user => user.UserEncryptValue)
.Where(grp => grp.Count() > 1 && grp.Any(usr => usr.UserId == searchId))
.SelectMany(u => u);
This groups on the UserEncryptValue and only selects groups that have more than 1 value (has a match) and at least 1 of the user ids is equal to the searchId.
Table.Where(n => Table.Any(o => !(o === n) && o.UserEncryptValue == n.UserEncryptValue)).Select(n => n.UserID)
Will return a collection of user id's for members of collection Table where at least on other member of the table has the same value UserEncryptValue but is not the same object
Learn LINQ to understand how this works and what you can do to tweak it.
One way is to use GroupBy. In this case you would group by UserEncryptValue.
You can then examine each group and check which users are in each group.

LINQ QUERY TABLE

The number increases by 1 in the database as a staff member views something.
Example
abab : 1
cbcb : 1
dcdc: 1
abab : 1
abab : 1
I want to print who viewed how much in the table.
Example
abab : 3
cbcb : 1
dcdc : 1
but it doesn't work the way I want. The code I wrote is below
Count = _viewHistoryRepository.GetByExpression(f => f.MemberId == c.MemberId).Sum(s=> s.ViewsCount)
Output:
abab : 3
abab : 3
abab : 3
cbcb : 1
dcdc: 1
I want each name to appear once. Thank you
You need to use GroupBy then:
IEnumerable<string> query = _viewHistoryRepository
.GroupBy(x => x.MemberId)
.Select(g => $"{g.Key} : {g.Sum(x => x.ViewsCount)}");
So apparently you have a class similar to this:
class StaffMemberView
{
public string Name {get; set;}
public int ViewCount {get; set;} // in your input always 1
... // other properties
}
If your input indeed always have a value 1, it is enough to make groups of StaffMemberviews that have the same value for property Name. In parameter resultSelector count the number of elements in each group:
IEnumerable<StaffMemberView> staffMemberViews = ...
var result = staffMemberViews.GroupBy(
// keySelector: make groups with the same value for Name:
staffMemberView => staffMemberView.Name,
// parameter resultSelector, for every Name, and all StaffMemberViews that
// have this Name, make one new:
(name, staffMembersViewsWithThisName) => new
{
Name = name,
ViewCount = staffMemberViewsWithThisName.Count(),
});
If parameter ViewCount sometimes is not 1, then it is not enough to just Count the StaffMemberViews in each group, but you have to Sum the values of ViewCount.
Parameter resultSelector changes:
(name, staffMembersViewsWithThisName) => new
{
Name = name,
ViewCount = staffMemberViewsWithThisName
.Select(staffMemberView => staffMemberView.ViewCount)
.Sum(),
});

Linq: Group by with OR condition

Below are the records where we are trying to group the records by the following OR conditions:
Name is same
Email is same
Phone is same
Is there a way in LINQ to Group By with Or condition?
Name Email Phone Id
--- --------- ------------ ----------
Rohan rohan#s.com NULL 1
R. Mehta rohan#s.com 9999999999 2
Alex alex#j.com 7777777777 3
Lisa John john#j.com 6666666666 4
Lisa lisa#j.com 6666666666 5
Siri siri#s.com NULL 6
RM info#s.com 9999999999 7
Lisa NULL NULL 8
Lisa John m#s.com 7777777757 9
Output Expected
Group 1:
Key: Rohan
RecordIds: 1,2,7 (As `Id:1` has same email as `Id:2`, `Id:2` has same
phone number as `Id:7`.)
Group 2:
Key: Lisa John
RecordIds: 4,5,8,9 (As `Id:4` has same phone number as `Id:5`. While `Id:5`
has the same name as `Id:8`. As `Id:9` has the same name
as `Id: 4`, include that)
3 and 6 are not part of the output as the output are only group with more than 1 record
Key can be anything I just put in a random key.
If record 9 had email-id: rohan#s.com then:
Output
Group 1:
Key: Rohan
RecordIds: 1,2,7,4,5,8,9
NOTE: Input is SQL table to be read through LINQ to SQL. So query performance too has to be taken into account.
Crud Solution:
A dirty solution would be the following:
Group the records by Name -> store result in var gl-1
Group the records by Email -> store result in var gl-2
Group the records by Phone -> store result in var gl-3
Take each result in gl-1 check if corresponding id is present in gl-2,gl-3. If so include those ids in gl-1
Take each result in gl-2 check if corresponding id is present in any result in gl-1 is so, include the exclusive ids to gl-1 record. If the loop encounters a result which is not present in gl-1, include it as a result in gl-1.
Do step 5 for gl-3.
GroupBy requires some definition of "equality". You could define an EqualityComparer with the logic you want, but you'll get inconsistent results. Your grouping breaks the transitive property of equality needed for grouping. In other words, if A=B and B=C then A=C must be true.
For example, the following pairs of items would be in the same group ("equal"):
A, B, C and A, D, E
A, D, E and F, G, E
but
A, B, C and F, G, E
would not be in the same group.
To get the output you want (e.g. item 9 in multiple groups) you'd need to use standard looping to recursively find all items that are "equal" to the first, then all items that are "equal" to that group, then all items that are "equal" to the third group, etc. Linq is not going to be very helpful here (except possibly for the searching within each recursive call).
Linq queries run linear which means once it has passed a new possible group it cant go back and work with it.
lets asume
public class aperson
{
public string Name;
public string Email;
public string Phone;
public int ID;
public aperson(string name,string email,string phone,int id)
{
Name = name;
Email = email;
Phone = phone;
ID = id;
}
}
example
new aperson("a","a#","1",1),
new aperson("b","b#","2",2),
new aperson("a","c#","2",3)
Iteration 1: create group 1 with ("a","a#","1") values
Iteration 2: create group 2 with ("b","b#","2") values
Iteration 3: here the system will have to group it with either group 1 or with group 2 but not both.
To fix this your iterator will have to go back to group 2 and group 1 and join them.
To solve this you will have to break it into steps.
Step1. Create the groups
Step2. Group by the created groups.
I think there are much better ways to do this. I am just illustrating the flow how this problem needs to be approached and why.
Code for solution
public static Dictionary<string, int> group = new Dictionary<string, int>();
public static void adduniquevalue(aperson person,int id)
{
if (person.Email != null && !group.Keys.Contains(person.Email))
{
group.Add(person.Email, id);
}
if (person.Phone != null && !group.Keys.Contains(person.Phone))
{
group.Add(person.Phone, id);
}
if (person.Name != null && !group.Keys.Contains(person.Name))
{
group.Add(person.Name, id);
}
}
public static void CreateGroupKeys(aperson person)
{
int id = group.Count;
List<int> groupmatches = new List<int>();
if (person.Email != null && group.Keys.Contains(person.Email))
groupmatches.Add(group[person.Email]);
if (person.Phone != null && group.Keys.Contains(person.Phone))
groupmatches.Add(group[person.Phone]);
if (person.Name != null && group.Keys.Contains(person.Name))
groupmatches.Add(group[person.Name]);
if (groupmatches.GroupBy(x=>x).Count() > 1)
{
int newid = groupmatches[0];
group.Keys.Where(key => groupmatches.Contains(group[key]))
.ToList()
.ForEach(key => { group[key] = newid; });
}
if (groupmatches.Count == 0)
adduniquevalue(person, id);
else adduniquevalue(person, groupmatches[0]);
}
public static int GetGroupKey(aperson person)
{
if (person.Email != null && group.Keys.Contains(person.Email))
return group[person.Email];
if (person.Phone != null && group.Keys.Contains(person.Phone))
return group[person.Phone];
if (person.Name != null && group.Keys.Contains(person.Name))
return group[person.Name];
else return 0;
}
This will create your groups in a dictionary which you could use in a normal group by method later on.
Like so:
people.ForEach(x => CreateGroupKeys(x));
var groups = people.GroupBy(x => GetGroupKey(x)).ToList();

Generate same ID out of same sets of IDs

I have an issue that I'll try to explain. My thought is to create a script in SSIS in C# and with that generate a list of IDs for each unique combination of IDs in a table.
I have a SQL server table which consists of two columns. The columns are IDs (I can make them numeric but in raw format they are alphanumeric strings). I want to generate a new ID out of the set of IDs in column 2 that are connected to column 1.
Col1 Col2 Generated ID
1 1
1 2 => 1
1 3
-----------
2 1 => 2
2 3
-----------
3 3
3 1 => 1
3 2
I'm thinking of a Hash function maybe? But how do I get the same ID out of the set for 1 and 3? Independent of order? Do I need to sort them first?
I needed "10 reputation" to post an image so I hope my illustration explains the issue...
As further examples to try to understand your problem, would you expect the following sets of values in Col2 to return something like '123' as the "Generated ID" value for all the listed cases below, like so?
Col2 => Generated ID
1,2,3 => 123
1,3,2 => 123
2,1,3 => 123
2,3,1 => 123
3,1,2 => 123
3,2,1 => 123
etc
If so, then based on the above assumptions and to answer your questions:
Yes, a Hash function could do it
How you get the same "Generated ID" for sets 1 and 3 (in your example) will depend on your GetHashCode() override/implementatio
Yes, you will probably need to sort, but again, that depends on your implementation.
Since you refer to using a C# script in SSIS, a possible C# implementation might be to implement a (very!) simple Hash class which given a set of Col2 values (for each data set), simply:
sorts the values for Col2 to get them in the 'right' order and
returns some integer representation of the sorted set of data to get the Hash (e.g., concatenate the int's as strings and then convert back to int)
The hash class could be instantiated in your (base?) class's GetHashCode() function, which is passed the Col2 values and performs steps (1) and (2) above, returning the hash code as needed.
Something like this might work for you (assuming you have access to Generics in the .NET version you're using):
namespace SimpleHashNamespace
{
public class SimpleHash
{
private readonly List<int> _data;
public SimpleHash(List<int> col2)
{
_data = col2;
}
public int GetMyHash()
{
_data.Sort();
string stringHash = string.Join("", _data);
return int.Parse(stringHash); // warning 1: assumes you always have a convertible value
}
}
public class MyDataSet
{
private readonly List<int> _dataSetValues;
public MyDataSet(List<int> dataSetValues)
{
_dataSetValues = dataSetValues;
}
public override int GetHashCode()
{
SimpleHash simpleHash = new SimpleHash(_dataSetValues);
return simpleHash.GetMyHash(); // warning 2: assumes the computed hash can fit into the int datatype given that GetHashCode() has to return int
}
}
public partial class Program
{
private static void Main(string[] args)
{
// how you split up Col1 to get your list of int's dataset is up to you
var myDataSet1 = new MyDataSet(new List<int>(new int[] { 1,2,3 }));
Console.WriteLine(myDataSet1.GetHashCode());
var myDataSet2 = new MyDataSet(new List<int>(new int[] { 2,1,3 }));
Console.WriteLine(myDataSet2.GetHashCode());
var myDataSet3 = new MyDataSet(new List<int>(new int[] { 3,2,1 }));
Console.WriteLine(myDataSet3.GetHashCode());
Console.ReadLine();
}
}
}
Obviously this is a trivial implementation however given the simplicity of the problem as it has been specified, perhaps this will suffice?
CREATE TABLE T (Col1 INT, Col2 INT);
GO
INSERT INTO [dbo].[T]([Col1],[Col2])
VALUES (1,1), (1,2), (1,3), (2,1), (2,3), (3,3), (3,1), (3,2), (2,3),(2,1);
GO
SELECT
T1.Col1,
(
SELECT Convert (VARCHAR,Col2) + ','
FROM T T2
WHERE T2.Col1 = T1.Col1
ORDER BY Col2
FOR XML PATH('')
) AS Col2_Cat
INTO X
FROM T T1
GROUP BY Col1 ;
SELECT T.Col1, T.Col2, Y.Col3
FROM T
INNER JOIN
(
SELECT X1.Col1, Min (X2.Col1) AS Col3 FROM X X1
----inner join X X2 on HASHBYTES ('SHA1',X1.Col2_Cat) = HASHBYTES('SHA1',X2.Col2_Cat)
inner join X X2 on X1.Col2_Cat = X2.Col2_Cat
GROUP BY X1.Col1
) AS Y
ON T.Col1 = Y.Col1;
DROP TABLE X
DROP TABLE T

Sort members of a list of type enum by specific item

I have an enum:
public enum Fruits
{
Apple = 14,
Lemon = 174,
Grapes = 200,
Peach = 1
}
and a list by this enum:
IEnumerable<Fruits> Fruits = new List<Fruits>();
By default when I call getValues on the enum it sorts the entries by their id.
I show the list as a dropdown in the UI and want to sort the members of the list in specific order. In my sample I want Lemon to be the first item in the list.
I tried to order the items by the Lemon entry with something like this:
Fruits.OrderBy(f => f.Lemon);
but I am not allowed to do this f.Lemon in this context. Maybe I can foreach the list remove the Lemon item and then insert it as a first entry.
I am quite new to programming and I have found some similar questions but not with enum type.
You can use OrderByDescending + ThenBy:
fruits.OrderByDescending(f => f == Fruits.Lemon)
.ThenBy(f => f);
Note that the variable should have a different name than the enum type (I've used lowercase fruits).
If you want to order second by the name:
.ThenBy(f => f.ToString());
f == Fruits.Lemon returns a bool which you can order by. It's similar to SQL CASE:
ORDER BY CASE WHEN Fruit = 'Lemon' THEN 1 ELSE 0 END DESC, FRUIT ASC

Categories

Resources