Getting Multiple Lists and displaying them to the View - c#

I have a system where I enter in other, employee, and dealer information as such (there is more fields but trying to keep it simple).
+----+---------+--------------+------------+-------+
| ID | itemId | memberTypeId | MemberType | price |
+----+---------+--------------+------------+-------+
| 1 | 202 | 2 | employee | 2.00 |
| 2 | 202 | 3 | dealer | 3.00 |
| 3 | 101 | 1 | other | 4.00 |
+----+---------+--------------+------------+-------+
I’m trying to make the Update functionality on my site. When I make a DB call based on the ItemId to get everything.
Here is such code from helper class:
public class Item {
public static List<ItemOption> GetItemOpttions(long itemID)
{
using (DBContext context = new DBContext())
{
List<ItemOptionDTO> ItemOptionsDto = (
from I in context.ItemOptions
where I.ItemID == itemID
select new ItemOptionDTO
{
ItemID = I.ItemID,
MemberTypeId = I.MemberTypeId
MemberType = I.MemberType,
Price = I.Price,
}).ToList();
return ItemOptionsDto;
}
}
}
So, when I get the data and store it in a list. It’s either one row of data or two rows based on how it was saved. The option “Other” will always be saved into the DB as one row of data as where “employee and dealer” will be saved as two separate row sharing the same ItemId. When called the number of rows will vary based on each item created at an earlier date/time.
I am trying to get this info back to the controller and send it to the View showing the correct values that might get updated. Here is what I have in the controller. I'm not sure if this is the correct way of doing this or if there is a better way.
Also to add that the if the item was saved as an employee and dealer it will leave the other list empty/null. I don't think I can do this because it will cause a null exception error
This is what I have so far in the controller:
public ActionResult UpdateItem(long itemID) {
List<ItemOptionDTO> itemOptionDto = Item.GetItemOpttions(itemID);
var other = itemOptionDto.Where(x => x.MemberTypeId == 1).FirstOrDefault();
var employee = itemOptionDto.Where(x => x.MemberTypeId == 2).FirstOrDefault();
var dealer = itemOptionDto.Where(x => x.MemberTypeId == 3).FirstOrDefault();
UpdateItemViewModel viewModel = new UpdateItemViewModel(itemID, employee, dealer, option)
{
ItemId = option.ItemId,
MemberType = option.MemberType,
Price = other.price
ItemId = employee.ItemId,
MemberType = employee.MemberType,
Price = employee.price
ItemId = dealer.ItemId,
MemberType = dealer.MemberType,
Price = dealer.price
};
return View(viewModel);
}
Let me know if there is anything else I can provide.

Related

combing two models and only retrieving a.firstname, a.lastname, b.name and returning as list to populate in mvc view using linq

I have a UserTbl and a CongregationTbl and I am trying to combine them so that I can retrieve a.FirstName, a.LastName and b.Name.
UserTbl
| C_ID | FirstName | LastName |
+------+-----------+----------+
1 Jim Jones
2 Frank Snow
1 Alice Cruz
2 Sarah Lee
CongregationTbl
| ID | Name |
+------+-----------+
1 Bellham
2 Fortworth
What I want to do return a list and populate that into a view
Created view
| Name | FirstName | LastName |
+--------+-----------+----------+
Bellham Jim Jones
Fortworth Frank Snow
Bellham Alice Cruz
Fortwroth Sarah Lee
This is what I have so far. It returns data, but I cannot get it into my list.
using (Model1 dc = new Model1())
{
var id = (from b in dc.CongregationTbls select b);
var list = from i in dc.UserTbl
where i.AccountConfirmed == false
select new
{ id.FirstOrDefault().Name, i.FirstName, i.LastName };
MergeModel MyModel = new MergeModel();
MyModel.PendingUsers = list.ToList();
return View(myModel);
}
You should model your merged one like this. It's like making a custom model that allocates the first two models's important fields:
public class MergedModel{
public string congregation {get;set;}
public string firstname {get;set;}
public string lastname {get;set;}
}
Then fill that model with the two models' data like this.
var merged = from user1 in UserTbl
join congregation1 in CongregationTbl on user1.C_ID equals congregation1.ID
select new MergedModel {congregation = congregation1.Name, firstname = user1.FirstName, lastname = user1.LastName };
Also, please note that var merged will converted as IEnumerable<MergedModel>. If you use the list as a return to your view to be called as #model IEnumerable<yourproject.Models.MergedModel> then it should work. Otherwise you can just reassign var merged like so:
List<MergedModel> merged2 = merged.ToList();
This is how I do it. I hope it helps you in any way.

Linq GroupBy throws ArgumentOutOfRangeException

I have these two tables
Animals Activities
+----+-------+ +----+------------+----------+------------+
| Id | Name | | Id | Activity | FkAnimal | Date |
+----+-------+ +----+------------+----------+------------+
| 1 | Cats | | 1 | Ball | 2 | 2015-05-21 |
+----+-------+ +----+------------+----------+------------+
| 2 | Dogs | | 2 | Pet | 2 | 2015-06-07 |
+----+-------+ +----+------------+----------+------------+
| 3 | Birds | | 3 | Running | 1 | 2014-11-03 |
+----+-------+ +----+------------+----------+------------+
| 4 | Kill a fly | 1 | 2014-08-05 |
+----+------------+----------+------------+
| 5 | Kill a fly | 3 | 2014-08-05 |
+----+------------+----------+------------+
What I want is the result of this query
SELECT Animals.Name, Animals.Id, Activities.Data
FROM Activities
INNER JOIN Animals ON Animals.Id = Activities.Id
GROUP BY Animals.Name, Animals.Data
In LINQ from the Entity Framework
Here's my attempt:
//My repository is of type IRepository<Activities>
var list = Repository.GetAll().GroupBy(a => a.Animals).Select((grouping,i) => new {
name = grouping.Key.Name,
id = grouping.Key.Id,
data = grouping.ElementAt(i).Data
}).ToList();
Unfortunately the ToList() method generate ArgumentOutOfRangeException, and if I debug the lambda it shows that i goes out of range
The i in .Select((grouping,i) => is the index of the group. In your example, .GroupBy(a => a.Animals) will return an IGrouping which is, essentially, just an IEnumerable with a Key property. The result from .GroupBy(a => a.Animals) will, loosely, look something like this (not sure exactly what your DbContext looks like):
{[
{
Key: Dogs
GetEnumerator(): [
{
Id: 1
Activity: Ball
Date: 2015-05-21
},
{
Id: 2
Activity: Pet
Date: 2015-06-07
}
]
},
{
Key: Cats
GetEnumerator(): [
{
Id: 3
Activity: Running
Date: 2014-11-03
},
{
Id: 4
Activity: Kill a fly
Date: 2014-08-05
}
]
},
{
Key: Birds
GetEnumerator(): [
{
Id: 5
Activity: Kill a fly
Date: 2014-08-05
}
]
}
]}
The Select method is iterating over the groups, not the elements in the group. So the i in .Select((grouping,i) =>, in this case, refers to the index of the group (there are three groups) not an element in a group. Within your select you are calling data = grouping.ElementAt(i).Data, grouping in this case is an IGropuing which is an IEnumerable so ElementAt(i) is asking for the ith element in whichever group is currently being evaluated. By the time you get the third group i will be 2 but there is only one element in the group, hence the exception; at least in this example, your groups may come back in a different order but the principle is the same.
You probably want something like this:
var list =
Repository
.GetAll()
.GroupBy(a => a.Animals)
.Select(grouping => new {
name = grouping.Key.Name,
id = grouping.Key.Id,
data = grouping.Select(x => x)
}).ToList();
does this work...
var res= from act in Repository.GetAll()
let anm=act.Animals.Single(a=>a.Id=act.FkAnimal)
select new {
anm.Id, anm.Name, act.Activity
};

Linq expression checkin if one user is following another

I have a table that stores followers and followees.These are based on the guids they have.
before i want to make this relation i want to check and see if the person is already following the person
EDIT
bool userExist = _databaseEntities.Users.Count(e => e.UserName == followerName) > 0;
if(userExist)
{
var user1 = _databaseEntities.Users.FirstOrDefault(y => (y.UserName == username));
var user2 = _databaseEntities.Users.FirstOrDefault(z => (z.UserName == followerName));
So i get two users and check if they are there and then check if their userIds are in the table of followers forming a relationship.
so I have this _db.Followers.Count(c => (c.UserId == user1.UserId && c.FollowerId == user2.UserId) < 0 );
but it always comes out as 0 even if the relation is there
How can i do this right?
If i understand correctly, you have a table like this:
| UserId | FollowerId |
|----------|--------------|
| Homer | Marge |
| Homer | Lisa |
| Marge | Homer |
| Marge | Bart |
| Bart | |
| Lisa | Bart |
|----------|--------------|
And the related User class should contain at least a string property for the UserId and a Collection of Users (those who the user is following)
So you can have a method inside User like this:
public bool CanFollow(User followee)
{
return !Followee.Any(x => x.UserId == followee.UserId);
}
It's easier and more logical and you simply use it like that
User homer = _db.Followers.Where(x => x.UserId == "Homer").FirstOrDefault();
User marge = _db.Followers.Where(x => x.UserId == "Marge").FirstOrDefault();
// can Homer follow Marge?
homer.CanFollow(marge);

How to execute nested query in Linq

I have a LINQ class of this format in C#:
class Vehicle
{
int _VehicleID
int _ModelID
EntetySet<Cars> _AllCars
EntetySet<Bus> _AllBus
EntetyRef<Driver> _Person
}
Cars table
CarsID | Manufacturer | Type
1000 | Honda | Diesel
1001 | Mitsubishi | Petrol
1002 | Maruti | Diesel
Bus table
BusID | Manufacturer | Type
2000 | Volvo | Diesel
2001 | TATA | Petrol
2002 | layland | Petrol
From the UI, I will get a Vehicle ID as a parameter. Based on that, all the cars, Bus and its associated tables will get copied to a variable. That is:
Vehicle v1 = new Vehicle();
v1 = dc.vehicle.where(v => v.vehicleID == param.vehicleID).findfirst();
My v1 has all the table and its contents which satisfies the above condition.
Now, I want to filter some more based on the table content present in table cars and bus; i.e based on type of vehicle petrol or diesel.
If I want to copy all the petrol cars and Buses using a query statement in a single line, please tell me the way.
Thanks in advance.
** Edit based upon comments **
The logic of your question somehow slipped by me, because I was taking a logical Human approach on vehicle. Whenever I look at this Vehicle class I instantly see cars and busses as vehicles to.
This indicates more that the naming is poorly chosen.
But no more judging from me.
I understand you want one vehicle by id and you want the result to only contain cars and busses riding on let's say Petrol, in a single line.
If it is translated to SQL than I don't know how far the tree can go within a select, but if it is in memory than you can go a long way inside a subselect.
You could use a 'Model' class to achieve that or you could go with an anonymous type, but I will give an example for a 'Model' class:
Example:
public class VehicleModel
{
public int VehicleID { get; set; }
public int ModelID { get; set; }
public List<Cars> Cars { get; set; }
public List<Bus> Buses { get; set; }
}
var vehicleID = 1; // just for the example of course.
var fuelType = "Petrol";
var vehicle = (from v in dc.vehicle
where v._VehicleID == vehicleID
select new VehicleModel
{
VehicleID = v._VehicleID,
ModelID = v._ModelID,
Cars = v._AllCars.Where(car => car.Type == fuelType).ToList(),
Buses = v._AllBus.Where(bus => bus.Type == fuelType).ToList()
}).SingleOrDefault();
// use FirstOrDefault() when _VehicleID is NOT unique to get TOP 1
Do not modify the EntitySets within the Entity itself, always use a model for these things, because if you would do that and call save changes on your EntityContainer all sorts of things could go wrong.
If you want to know about anonymous types take a look here:
http://msdn.microsoft.com/en-us/library/bb397696(v=vs.100).aspx
Also take a look here for Linq examples:
http://code.msdn.microsoft.com/101-LINQ-Samples-3fb9811b
- before edit
Do you mean this:
var query = dc.vehicle.Where(v =>
v._AllCars.Any(c => c.Manufacturer == "Honda") ||
v._AllBuss.Any(b => b.Manufacturer == "Volvo"));
This will give you all vehicles where the cars are Honda Or the Busses are Volvo.
Which will be:
1000 | Honda | Diesel
2000 | Volvo | Diesel
the result is an IEnumerable containing all or no items satisfying the criteria.
If you only want the first hit you can do:
//if it must exist, otherwise this throws an exception
var firstVehicle = query.First();
//if it may exist, otherwise null
var firstVehicle = query.FirstOrDefault();
It seems that you want something like this:
var v1 = dc.vehicle.Where(v => v.vehicleID == param.vehicleID
&& v.Cars.All(c => c.Type == "Petrol")
&& v.Buses.All(c => c.Type == "Petrol")).First();
)
to get a "Vehicle" of which all cars and buses have petrol. (Note that I use "Cars" and not the unconventional name "_AllCars", etc.).
Edit
Or:
var v1 = dc.vehicle.Where(v => v.vehicleID == param.vehicleID)
.Select(v => new {
Id = v.vehicleID,
Cars = v.Cars.Where(c => c.Type == "Petrol"),
Buses = v.Buses.Where(c => c.Type == "Petrol")
}).First();
to get an anonymous type with filtered collections.

Search on all fields of an entity

I'm trying to implement an "omnibox"-type search over a customer database where a single query should attempt to match any properties of a customer.
Here's some sample data to illustrate what I'm trying to achieve:
FirstName | LastName | PhoneNumber | ZipCode | ...
--------------------------------------------------
Mary | Jane | 12345 | 98765 | ...
Jane | Fonda | 54321 | 66666 | ...
Billy | Kid | 23455 | 12345 | ...
If the query was "Jane", I'd expect row #1 to be returned as well as row #2.
A query for 12345 would yield rows #1 and #3.
Right now, my code looks pretty much like this:
IEnumerable<Customer> searchResult = context.Customer.Where(
c => c.FirstName == query ||
c.LastName == query ||
c.PhoneNumber == query ||
c.ZipCode == query
// and so forth. Fugly, huh?
);
This obviously works. It smells like really bad practice to me, though, since any change in the Entity (removal of properties, introduction of new properties) would break stuff.
So: is there some LINQ-foo that will search across all properties of whatever Entity I throw at it?
first find all properties within Customer class with same type as query:
var stringProperties = typeof(Customer).GetProperties().Where(prop =>
prop.PropertyType == query.GetType());
then find all customers from context that has at least one property with value equal to query:
context.Customer.Where(customer =>
stringProperties.Any(prop =>
prop.GetValue(customer, null) == query));

Categories