Changing the name of major to aliasName - c#

everyone, I am trying to write code that checks if there is alias name show it and if there is not then show the full name
This is my data:
This is My Code for showing FullName:
var TopStudents = await GetTopStudentsFromDb(count);
var codes = TopStudents.Select(e => e.StudentCode).Distinct().ToList();
var Students = await GetStudeentByCode(codes);
foreach (var St in TopStudents)
{
St.StudentsName =
Students.FirstOrDefault(e => e.Code == St.StudentCode)?.NameMajor.Refine();
}
this code works and shows the name now I want to change it to show the alias name of the major what should I do?
I want to check if it has Alias name show it if it doesn't then show the name.

The best will be to add a property on you TopStudens type that uses the null null-coalescing operator ?? - like:
public class TopStudents {
[NotMapped] // not persisted in database.
public string AliasOrNameMajor => Alias ?? NameMajor;
}
and then do it this way:
foreach (var St in TopStudents)
{
St.StudentsName =
Students.FirstOrDefault(e => e.Code == St.StudentCode)?.AliasOrNameMajor;
}

Related

How to make a join table search with Entity Framework?

So I made a windows form which has a search textbox that will return the parts of string that you have entered in the datagrid. However, in my attempt to code this following event. The datagrid shows boolean instead.
Which parts of the code is making all these result turns boolean and how can i fix this?
private void txtSearch_TextChanged(object sender, EventArgs e)
{
this.dataGridView1.DataSource = null;
this.dataGridView1.Rows.Clear();
using (var context = new edeappEntities1())
{
var data = context.bookingorders
.Join(
context.addressbooks,
booking => booking.addrID,
address => address.addrID,
(booking, address) => new
{
accID = booking.accID.Contains(txtSearch.Text),
bookId = booking.bookingID.Contains(txtSearch.Text),
companyName = address.companyName.Contains(txtSearch.Text),
address = address.addressLn1.Contains(txtSearch.Text) || address.addressLn2.Contains(txtSearch.Text) ||
address.addressLn3.Contains(txtSearch.Text),
region = address.region.Contains(txtSearch.Text),
postcode = address.postcode.Contains(txtSearch.Text),
contact = address.contectName.Contains(txtSearch.Text),
phone = address.phoneNo.Contains(txtSearch.Text),
fax = address.faxNo.Contains(txtSearch.Text),
telex = address.telexNo.Contains(txtSearch.Text),
pickupTime = booking.pickupDate.Contains(txtSearch.Text)
|| booking.pickupTime.Contains(txtSearch.Text)
}
).ToList();
foreach (var db in data)
{
dataGridView1.Rows.Add(db.accID, db.bookId, db.companyName, db.address, db.region,
db.postcode, db.contact, db.phone, db.fax, db.telex, db.pickupTime);
}
}
}
My modelling structure: model1.edmx
Search result is boolean: link
You are getting a Boolean result in all the columns because you are creating a new anonymous type and assigning the result of string.Contains() method to each property in that new anonymous type and string.Contains() returns a Boolean(bool).
For example, if I do this:
string str = "Hello!"
bool result = str.Contains("o");
Here, the Contains() method will return a Boolean value indicating whether the string contains the specified substring("o") in it. The return value here will be true which will be assigned to result.
In your code, you do something similar for each field:
accID = booking.accID.Contains(txtSearch.Text)
This will check if booking.accID contains the string searched by the user which is captured in txtSearch.Text. If your booking.accID contains txtSearch.Text, the method will return true and false if it does not contain the search text. This will create a new variable of type bool called accId and the return value will be stored in accId on the left-hand side of =.
Anonymous Types
In C#, an anonymous type is a quick way to create a wrapper object containing a set of properties without actually creating a class.
For instance, I want an object containing details about a person without creating a Person class, I can do this:
var myPerson = new { Name = "John", Age = 25, Salary = 10_000L };
Now, I have an object containing the properties Name, Age and Salary without even creating a Person class. The compiler creates a hidden class in the background. More on anonymous types here.
You are creating a lambda function that returns an anonymous type as the fourth parameter of the Join() method. This lambda function will be called on each result of the join operation.
Solution
The filtering condition should be specified in a Where() method instead of assigning it to properties in the anonymous type. The anonymous type should be used to capture and combine the two results:
var searchData = context
.bookingorders
.Join(
context.addressbooks,
booking => booking.addrID,
address => address.addrID,
(booking, address) => new
{
Booking = booking,
Address = address
})
.Where(data =>
data.Booking.bookingID.Contains(txtSearch.Text) ||
data.Address.companyName.Contains(txtSearch.Text) ||
data.Address.addressLn1.Contains(txtSearch.Text) ||
data.Address.addressLn2.Contains(txtSearch.Text) ||
data.Address.region.Contains(txtSearch.Text) ||
data.Address.postcode.Contains(txtSearch.Text) ||
data.Address.contectName.Contains(txtSearch.Text) ||
data.Address.phoneNo.Contains(txtSearch.Text) ||
data.Address.faxNo.Contains(txtSearch.Text) ||
data.Address.telexNo.Contains(txtSearch.Text) ||
data.Booking.pickupDate.Contains(txtSearch.Text) ||
data.Booking.pickupTime.Contains(txtSearch.Text)
)
.ToList();
foreach(var row in searchData)
{
dataGridView1.Rows.Add(
row.Booking.bookingId,
row.Address.companyName,
$"{row.Address.addressLn1} {row.Address.addressLn2}",
row.Address.region,
row.Address.postcode,
row.Address.contectName,
row.Address.phoneNo,
row.Address.faxNo,
row.Address.telexNo,
row.Booking.pickupDate,
row.Booking.pickupTime
);
}

C# for each property get both value and name

I'm sending a JSON object through PUT from angularJS to c#, which has a property name and a value.
I'm trying to loop for each property and read both name and the value, but it fails. I have succeed to read only the name or only the value though with the below code:
Newtonsoft.Json.Linq.JObject cbpcs = pricestopsale.cbPricegroups;
foreach (string pricegroupInfo in cbpcs.Properties().Select(p => p.Value).ToList())
{
// I want to be able to do something like this inside here
if(pricegroupInfo.Value == "Something") {
// do stuff
}
}
In my above example pricegroupInfo has the value, if i change .Select(p => p.Name).ToList()) i get the name of the property.
What can I do if i want to get both name and value inside my loop ?
Update 1: The property Name is unknown to me, it's generated dynamically so I dont know in advance the property name.
Update 2: I want to be able to compare the value and the name as a string inside the loop.
Try using an anonymous object in the select.
Newtonsoft.Json.Linq.JObject cbpcs = pricestopsale.cbPricegroups;
foreach (var pricegroupInfo in cbpcs.Properties().Select(p => new { p.Value, p.Name }).ToList())
{
// read the properties like this
var value = pricegroupInfo.Value;
var name = pricegroupInfo.Name;
if(pricegroupInfo.Value.ToObject<string>() == "foo")
{
Console.WriteLine("this is true");
}
}
Reference: JObject.Properties Method
Newtonsoft.Json.Linq.JObject cbpcs = pricestopsale.cbPricegroups;
foreach (var pricegroupInfo in cbpcs.Properties())
{
if(pricegroupInfo.Name == "propName" // your property name
&& pricegroupInfo.Value.ToString() == "something") { // your value
// do stuff
}
}
As you can see, it returns IEnumerable<JProperty> which use can iterate and make use of to get property Name and Value
Try this
foreach(var prop in cbpcs.GetType().GetProperties()) {
Console.WriteLine("{0}={1}", prop.Name, prop.GetValue(foo, null));}

Filter null properties from list using Linq

I have a method that accepts a variable that has a list of properties connected to it. What I need to do is create a linq query that will flag the current variable coming in as missing an "address" and add it to a list.
public void Teachers(List<Teacher> teachers)
{
foreach (Name name in teachers)
{
int age = program.CalculateAge(name.BirthDate.Year);
Name address = FilterAddress(name);
// Output Teachers Name - First Name, Last Name
if (name.Type.Equals(Name.NameType.Teacher))
{
OutputToConsole(name.FirstName, name.LastName, age);
program.WriteAddress(name);
}
}
Console.WriteLine();
}
Above is the method that will add the current variable in foreach loop to the FilterAddress Method. Below is where the variable is being passed. This variable has a List property named "Address" that is connected to it. This address can be null. I need to select each name with an address of null and add it to a list. But as you guessed, my LINQ code below doesn't work and just breaks.
public Name FilterAddress(Name name)
{
var NullItems = name.Select(x => x.Addresses).OfType<Name>();
return NullItems;
}
public Name[] FilterAddress(Name name)
{
return name.Where(x => string.IsNullOrEmpty(x.Addresses))
.Select(x => x.Name)
.ToArray();
}
Only need to add the "if null" check in the query to return if Adresses is null.
var NullItems = name.Where(x => x.Addresses == null);

Cannot implicitly convert type '.List<AnonymousType#1>' to '.List<WebApplication2.Customer>'

In the following code that returns a list:
public List<Customer> GeAllCust()
{
var results = db.Customers
.Select(x => new { x.CustName, x.CustEmail, x.CustAddress, x.CustContactNo })
.ToList()
return results;
}
I get an error reporting that C# can't convert the list:
Error: Cannot implicitly convert type System.Collections.Generic.List<AnonymousType#1> to System.Collections.Generic.List<WebApplication2.Customer>
Why is that?
Here's a screenshot showing some additional information that Visual Studio provides in a tooltip for the error:
Is it right way to return some columns instead of whole table....?
public object GeAllCust()
{
var results = db.Customers.Select(x => new { x.CustName, x.CustEmail, x.CustAddress, x.CustContactNo }).ToList();
return results;
}
When you look the code:
x => new { ... }
This creates a new anonymous type. If you don't need to pull back only a particular set of columns, you can just do the following:
return db.Customers.ToList();
This assumes that Customers is an IEnumerable<Customer>, which should match up with what you are trying to return.
Edit
You have noted that you only want to return a certain subset of columns. If you want any sort of compiler help when coding this, you need to make a custom class to hold the values:
public class CustomerMinInfo
{
public string Name { get; set; }
public string Email { get; set; }
public string Address { get; set; }
public int? ContactNumber { get; set; }
}
Then change your function to the following:
public List<CustomerMinInfo> GetAllCust()
{
var results = db.Customers.Select(x => new CustomerMinInfo()
{
Name = x.CustName,
Email = x.Email,
Address = x.Address,
ContactNumber = x.CustContactNo
})
.ToList();
return results;
}
This will work, however, you will lose all relationship to the database context. This means if you update the returned values, it will not stick it back into the database.
Also, just to repeat my comment, returning more columns (with the exception of byte arrays) does not necessarily mean longer execution time. Returning a lot of rows means more execution time. Your function is returning every single customer in the database, which when your system grows, will start to hang your program, even with the reduced amount of columns.
You are selecting to an anonymous type, which is not a Customer.
If you want to do (sort of) this, you can write it like this:
return db.Customers.Select(x => new Customer { Name = x.CustName, Email = x.CustEmail, Address = x.CustAddress, ContactNo = x.ContactNo }).ToList();
This assumes the properties on your Customer object are what I called them.
** EDIT ** Per your comment,
If you want to return a subset of the table, you can do one of two things:
Return the translated form of Customer as I specified above, or:
Create a new class for your business layer that only has only those four fields, and change your method to return a List<ShrunkenCustomer> (assuming ShunkenCustomer is the name that you choose for your new class.)
GetAllCust() is supposed to return a List of Customer, Select New will create a list of Anonymous Types, you need to return a list of Customer from your query.
try:
var results = db.Customers.Select( new Customer{CustName = x.CustName}).ToList(); //include other fields
I guess Customer is a class you have defined yourself?
The my suggestion would be to do something like the following:
var results = db.Customers.Select(x => new Customer(x.Custname, x.CustEmail, x.CustAddress, x.CustContactNo)).ToList();
The reason is that you are trying to return a list of Customer but the results from your link is an anonymous class containing those four values.
This would of course require that you have a constructor that takes those four values.
Basically whatever u got in var type, loop on that and store it in list<> object then loop and achieve ur target.Here I m posting code for Master details.
List obj = new List();
var orderlist = (from a in db.Order_Master
join b in db.UserAccounts on a.User_Id equals b.Id into abc
from b in abc.DefaultIfEmpty()
select new
{
Order_Id = a.Order_Id,
User_Name = b.FirstName,
Order_Date = a.Order_Date,
Tot_Qty = a.Tot_Qty,
Tot_Price = a.Tot_Price,
Order_Status = a.Order_Status,
Payment_Mode = a.Payment_Mode,
Address_Id = a.Address_Id
});
List<MasterOrder> ob = new List<MasterOrder>();
foreach (var item in orderlist)
{
MasterOrder clr = new MasterOrder();
clr.Order_Id = item.Order_Id;
clr.User_Name = item.User_Name;
clr.Order_Date = item.Order_Date;
clr.Tot_Qty = item.Tot_Qty;
clr.Tot_Price = item.Tot_Price;
clr.Order_Status = item.Order_Status;
clr.Payment_Mode = item.Payment_Mode;
clr.Address_Id = item.Address_Id;
ob.Add(clr);
}
using(ecom_storeEntities en=new ecom_storeEntities())
{
var Masterlist = en.Order_Master.OrderByDescending(a => a.Order_Id).ToList();
foreach (var i in ob)
{
var Child = en.Order_Child.Where(a => a.Order_Id==i.Order_Id).ToList();
obj.Add(new OrderMasterChild
{
Master = i,
Childs = Child
});
}
}

Why I can't remove item from ObservableCollection?

I filled some ObservableCollection<Employe> collection:
// Program.Data.Employees - it is ObservableCollection<Employe>.
Program.Data.Employees.Add(new Employe() { Name="Roman", Patronymic="Petrovich", Surname="Ivanov" });
Program.Data.Employees.Add(new Employe() { Name = "Oleg", Patronymic = "Vladimirovich", Surname = "Trofimov" });
Program.Data.Employees.Add(new Employe() { Name = "Anton", Patronymic = "Igorevich", Surname = "Kuznetcov" });
In other place of my code I try to remove some item from this collection:
// Program.Data.Employees - it is ObservableCollection<Employe>.
Employe x = Program.Data.Employees.First(n => n.Guid == emp.Guid); // x is not null.
Int32 index = Program.Data.Employees.IndexOf(x); // I got -1. Why?
Boolean result = Program.Data.Employees.Remove(x); // I got 'false', and item is not removed. Why?
// But this works fine:
Program.Data.Employees.Clear();
I can clear collection, but I can't remove necessary item. Why it happens?
UPD: Equals method of my Employe class
public bool Equals(Employe other) {
return
other.Guid == this.Guid &&
String.Equals(other.Name, this.Name, StringComparison.CurrentCultureIgnoreCase) &&
String.Equals(other.Patronymic == this.Patronymic, StringComparison.CurrentCultureIgnoreCase) &&
String.Equals(other.Surname == this.Surname, StringComparison.CurrentCultureIgnoreCase) &&
other.Sex == this.Sex &&
String.Equals(other.Post == this.Post, StringComparison.CurrentCultureIgnoreCase);
}
I tried the following code to reproduce your error:
class Employee
{
public string Name { get; set; }
public Guid Guid { get; set; }
}
// ...
ObservableCollection<Employee> employees = new ObservableCollection<Employee>();
var guid1 = Guid.NewGuid();
employees.Add(new Employee { Name = "Roman", Guid = guid1 });
employees.Add(new Employee { Name = "Oleg", Guid = Guid.NewGuid() });
var x = employees.First(e => e.Guid == guid1);
var index = employees.IndexOf(x); // index = 0, as expected
var result = employees.Remove(x); // result = true, as expected
It worked as expected. I would suggest, you set a breakpont at var x = ... and check, if
The collection really contains the item you're looking
If First() really returns that item
Then go to the next line and check, if index is returned correctly. And finally check again, if result is really false.
I see several possible causes of your code failing:
You didn't post the full code and something happens between x=Program.Data.Employees.First() and Program.Data.Employees.IndexOf()
You use multithreaded code (which also results in "something happening" between the two statements). In this case, you need to synchronize the access to the collection
You don't use a ObservableCollection directly but some derived class instead which is constructed by your data layer (such as DataServiceCollection, but this one should work fine too). In this case, check the actual type of your collection in the debugger
Another typical cause of errors with collection would be, if you try to remove items while iterating over the collection (i.e. inside a foreachloop): but in this case an exception should be thrown (and IndexOf should work fine), so this would only apply if you use some derived class which implements non-standard behaviour.
EDIT (in return to you posting your Equal method)
Your Equal method has a serious error in it:
String.Equals(other.Patronymic == this.Patronymic, StringComparison.CurrentCultureIgnoreCase)
... // applies also for following comparisons
should be
String.Equals(other.Patronymic, this.Patronymic, StringComparison.CurrentCultureIgnoreCase)
...
Also, if you're using a Guid, consider only comparing the GUIDs, since this usually means 'unique identifier', so it should be enough to identify some entity.

Categories

Resources