Dictionary<string, EmployeeInfo> employeeInfoList = new Dictionary<string, EmployeeInfo>();
employeeInfoList = EmployeeInfoProxy.GetAllEmployeeInfo(TenantId);
if (employeeInfoList != null)
{
List<EmployeeInfo> employee = new List<EmployeeInfo>(employeeInfoList.Values);
ViewData["Name"] = employee[0].Name;
ViewData["Salary"] = employee[0].Salary;
ViewData["Department"] = employee[0].Department;
ViewData["Designation"] = employee[0].Designation;
ViewData["Address"] = employee[0].Address;
ViewData["Address1"] = employee[0].Address1;
}
the above code is working fine.if the employee has only one record,so i had hardcoded employee[0].
if there are more rows,how to pass those index to employee(for eg employee[\i should get the value dynamically here].
If I understand your question correctly, given a List you could use linq to grab a single employee.
EmployeeInfo singleEmployee = employee.Where( x => x.Id).SingleOrDefault();
if (singleEmployee != null)
{
do something here
}
that said, I don't know if you have a 'key' against the employee like Id or similar.
To get by index, you have a bigger round trip (outputting the emploees to a grid or something similar, allowing a click that passes in the index of the employee you want, and access the single eployee that way).
Unless you're heavily employing caching in the 'EmployeeInfoProxy.GetAllEmployeeInfo()' method though, I'd say you want a 'GetEmployeeInfoById()' and again, I'll harp back to the need for your EmployeeInfo to have a unique Id of some description - you will make your life so much easier.
Hope this helps.
Cheers,
Terry
[in addition]
if employeeListInfo has 3 entries, then to access each of them I'd say the best way would be to create a viewmodel (it looks like this is MVC), but worst case scenario you could do:
List<EmployeeInfo> employee = new List<EmployeeInfo>(employeeInfoList.Values);
ViewData["Employees"] = employee;
then in your view, just do:
<% foreach(EmployeeInfo employeeDetails in ViewData["Employees"] as List<EmployeeInfo>) { %>
<!-- you will be looping through each employee here, so you can do as you wish
<% } %>
I wouldn't say this is best practice - using a ViewModel would likely represent a better way to do this, though the above will certainly give you a solution that will work in your case.
Related
I have struggle with adding the grouped data table with linq query to model property.
Here's my model
public class Ports
{
public String city { get; set; }
}
and here's my controller
public ActionResult ShipSchedule()
{
DatabaseContext db = new DatabaseContext();
var Ports = new Ports();
Ports.city = from m in db.ports_data group m by new { m.city } into n select new { n.Key.city };
return View();
}
I've replaced the model part to List<> and replaced again to another, but this part
Ports.city = (from m in db.ports_data group m by new { m.city } into n select new { newcity = n.Key.city }).ToList();
is still tell me that part cannot convert type 'system.collections.generic.list<<anonymous type: string newcity>>' to 'system.collections.generic.list<string>'
Did anyone know the correct ways from this?
and one more thing, I want to display that part to my view in dropdown, if anyone have a better ways
here's my view
#model example.Models.Ports
#{
List<SelectListItem> listItems = new List<SelectListItem>();
foreach (var mod in Model.city)
{
listItems.Add(new SelectListItem
{
Text = mod.ToString(),
Value = mod.ToString()
});
}
}
#Html.DropDownListFor(model => model.selected, listItems, "-- Select item --")
the error is telling you exactly what is wrong, you have a string but are trying to assign a list to it (two very different objects), you can simply:
public class Ports
{
public List<String> cities { get; set; }
}
which will make that string be valid, but a better practice would be make "Ports" a list and use it as List<Port> and each port will contain "city" (and all the other port properties).
but in any case to get all ports from the database you probably can do:
var ports = db.ports_data.ToList();
that should give you a list with all the ports in your database (no need to create that New Ports() and populate it, if you need to group by city it should be as easy as:
var ports = db.ports_data.GroupBy(x=>x.city).ToList();
in the comment you mentioned that you are getting duplicates, for that you may need distinct, but if you don't need duplicates you shouldn't be adding duplicates to the database to start with, so we would be touching the wrong end here, but in any case I believe you need Distinct() if combined with a select you will get only cities, different ones if there is duplicates:
var portsCities = db.ports_data.Select(x=>x.city).Distinct().ToList();
that will result in a List<string> of cities, all different
as you can see Linq have many ways to get exactly the data you need, I would play around with it and experiment, best way to learn!
I would also try to use LINQ method (as the examples above) if you are starting, it is easier to manage (more object oriented) you can see some examples here
I have started using performance wizard in visual studio 2012 because there was a slow method which is basically used to get all users from the datacontext. I fixed the initial problem but I am now curious if I can make it faster.
Currently I am doing this:
public void GetUsers(UserManagerDashboard UserManagerDashboard)
{
try
{
using (GenesisOnlineEnties = new GenesisOnlineEntities())
{
var q = from u in GenesisOnlineEnties.vw_UserManager_Users
select u;
foreach (var user in q)
{
User u = new User();
u.UserID = user.UserId;
u.ApplicationID = user.ApplicationId;
u.UserName = user.UserName;
u.Salutation = user.Salutation;
u.EmailAddress = user.Email;
u.Password = user.Password;
u.FirstName = user.FirstName;
u.Surname = user.LastName;
u.CompanyID = user.CompanyId;
u.CompanyName = user.CompanyName;
u.GroupID = user.GroupId;
u.GroupName = user.GroupName;
u.IsActive = user.IsActive;
u.RowType = user.UserType;
u.MaximumConcurrentUsers = user.MaxConcurrentUsers;
u.ModuleID = user.ModuleId;
u.ModuleName = user.ModuleName;
UserManagerDashboard.GridUsers.users.Add(u);
}
}
}
catch (Exception ex)
{
}
}
It's a very straight forward method. Connect to the database using entity framework, get all users from the view "vw_usermanager_users" and populate the object which is part of a collection.
I was casting ?int to int and I changed the property to ?int so no cast is needed. I know that it is going to take longer because I am looping through records. But is it possible to speed this query up?
Ok, first things first, what does your vw_UserManager_Users object look like? If any of those properties you're referencing are navigational properties:-
public partial class UserManager_User
{
public string GroupName { get { return this.Group.Name; } }
// See how the getter traverses across the "Group" relationship
// to get the name?
}
then you're likely running face-first into this issue - basically you'll be querying your database once for the list of users, and then once (or more) for each user to load the relationships. Some people, when faced with a problem, think "I know, I'll use an O/RM". Now they have N+1 problems.
You're better to use query projection:-
var q = from u in GenesisOnlineEnties.vw_UserManager_Users
select new User()
{
UserID = u.UserId,
ApplicationId = u.ApplicationID,
GroupName = u.Group.Name, // Does the join on the database instead
...
};
That way, the data is already in the right shape, and you only send the columns you actually need across the wire.
If you want to get fancy, you can use AutoMapper to do the query projection for you; saves on some verbosity - especially if you're doing the projection in multiple places:-
var q = GenesisOnlineEnties.vw_UserManager_Users.Project().To<User>();
Next up, what grid are you using? Can you use databinding (or simply replace the Grid's collection) rather than populating it one-by-one with the results from your query?:-
UserManagerDashboard.GridUsers.users = q.ToList();
or:-
UserManagerDashboard.GridUsers.DataSource = q.ToList();
or maybe:-
UserManagerDashboard.GridUsers = new MyGrid(q.ToList());
The way you're adding the users to the grid right now is like moving sand from one bucket to another one grain at a time. If you're making a desktop app it's even worse because adding an item to the grid will probably trigger a redraw of the UI (i.e. one grain at a time and, describing every grain in the bucket to your buddy after each one). Either way you're doing unnecessary work, see what methods your grid gives you to avoid this.
How many users are in the table? If the number is very large, then you'll want to page your results. Make sure that the paging happens on the database rather than after you've got all the data - otherwise it kind of defeats the purpose:-
q = q.Skip(index).Take(pageSize);
though bear in mind that some grids interact with IQueryable to do paging out-of-the-box, in that case you'd just pass q to the grid directly.
Those are the obvious ones. If that doesn't fix your problem, post more code and I'll take a deeper look.
Yes, by turning off change tracking:
var q = from u in GenesisOnlineEnties.vw_UserManager_Users.AsNoTracking()
select u;
Unless you are using all the properties on the entity you can also select only the columns you want.
var q = from u in GenesisOnlineEnties.vw_UserManager_Users.AsNoTracking()
select new User
{
UserId = u.UserId,
...
}
I have some code which I'm having problems which and hopefully somebody can assist me, basically I have a 'Player' class such as:
Player JanMccoy = new Player { playerFirstname = "Jan", playerSurname = "Mccoy", playerAge = 23,
playerCode = "MCC0001"};
I have about 10 players, all of which have a unique code to them self, basically this code is stored into a list box with the Name and Surname. How the data gets their isn't important, basically though there are 10 values in the listbox which look like "Jan Mccoy (MCC0001)"
Basically I want to now be able to get the age of the person in the class, I have an event for a button which when he gets the selected item from the listbox box I store into a string just the playerCode, which this code I need to be able to get the player age
I know this is SQL but I need something basically like:
SELECT * FROM MyClass WHERE playerCode = strPlayerCode
I however am not using SQL, I need something which can do that in C#
If I need to add anymore detail just ask, tried to explain as good as I can.
If you could point me into right direction also that be great also!
In c# there is Linq which works similar to SQL
For example:
SELECT * FROM MyClass WHERE playerCode = strPlayerCode
would be
var players = myListOfPlayers.Where(p => p.playerCode == strPlayerCode);
This will return a collection of all the players with that playercode
However, since you said the key is unique and you are only returning a single record FirstOrDefault will work fine without the need tor the where clause. like SELECT TOP 1 FROM ....
var player = myListOfPlayers.FirstOrDefault(p => p.playerCode == strPlayerCode);
Then I would try LINQ:
var player = players.Where(p => p.playerCode == "MCC001").FirstOrDefault();
Im developing a tool that needs to access to the names.nsf database inside IBM Lotus Notes, and, using the lotus contact ID (Employee ID) (this id will be provided by the user), retrieve the full information of the person (Name, Position, Phone #....)
I found an example at Codeproject.com (http://www.codeproject.com/Articles/18517/Lotus-Notes-Integration-with-Microsoft-NET-Platfor), however it takes around 10 minutes to get the information the way the example does it (the database has more or less 5000 entries), so I'm searching for a faster way of doing it (if I actually use Lotus notes for this it takes about a second!).
Is there a way to accomplish this task without having the user waiting for minutes?
Thought that maybe you can help me out with this one.
The sample you are using goes through the view using
NotesViewEntry viewEntry = notesViewCollection.GetNthEntry( rowCount );
This is (one of) the worst methods to use as it goes for every iteration from the top of the view and iterates through all docs until it reached the nth document.
There are two options:
1) Optimize this code by using
NotesViewEntry viewEntry = notesViewCollection.GetFirstEntry();
and at the end
viewEntry = notesViewCollection.GetNextEntry(viewEntry);
2) (in my humble opinion the better way): Change the code:
- you need a view with the first column sorted by your key => contact ID (Employee ID)
- You can the access the ViewEntry by a code like
LotusNotesView.GetEntryByKey( EmployeeID, true);
If you are lucky the names.nsf is full text indexed. If it's not you could try to ask if it could be full text indexed. When it's indexed you can get the person document quicly like this:
LotusNotesView.FTSearch("[EmployeeID]=1234567", 1);
NotesDocument docPerson = LotusNotesView.GetFirstDocument();
The use of GetNthEntry certainly causes some performance issues. I've taken the relevant code from that site and rewrote it to use the GetFirst/GetNext pattern, which is recommended for all view processing in Lotus Notes.
Note this hasn't been tested, of course. The point is to get the first entry in your collection, check that it is an object, and then process it. At the end of the loop, get the next entry and repeat until you hit null.
NotesViewEntryCollection notesViewCollection = LotusNotesView.AllEntries;
NotesViewEntry viewEntry = notesViewCollection.GetFirstEntry();
while (viewEntry != null)
{
//Get the first document of particular entry.
NotesDocument document = viewEntry.Document;
object documentItems = document.Items;
Array itemArray1 = (System.Array)documentItems;
for( int itemCount=0 ; itemCount< itemArray1.Length; itemCount++ )
{
NotesItem notesItem =
(Domino.NotesItem)itemArray1.GetValue( itemCount );
//compare field value with specific value entered by user
if( notesItem.Text !=null )
{
if( (notesItem.Text.ToUpper()).StartsWith( fieldValue ))
{
Contact contact = new Contact();
for( int icount=0 ; icount< itemArray1.Length; icount++ )
{
NotesItem searchedNotesItem =
(Domino.NotesItem)itemArray1.GetValue( icount );
string FieldName = searchedNotesItem.Name.ToString();
//For FirstName
if( searchedNotesItem.Name == "FirstName" )
contact.FirstName= searchedNotesItem.Text;
//For LastName
if( searchedNotesItem.Name == "LastName" )
contact.LastName = searchedNotesItem.Text;
//For Office Phone Number
if( searchedNotesItem.Name == "OfficePhoneNumber" )
contact.OfficePhoneNumber = searchedNotesItem.Text;
if( searchedNotesItem.Name == "InternetAddress" )
contact.EmailId = searchedNotesItem.Text;
}//end for
contactsList.Add( contact );
break;
}//End if
}
}
//Get the nth entry of the selected view according to the iteration.
NotesViewEntry viewEntry = notesViewCollection.GetNextEntry(viewEntry);
}
Why are you asking the user to provide his Employee ID? You should ask him to provide his Notes username (either FullName or ShortName), or his email address. Any of those can be looked up very quickly in the $Users view in names.nsf, giving you fast access to the document containing all the data that you need.
Note: I'm aware that some companies actually enter their Employee ID into the ShortName field in names.nsf. If that's the case for your organization, then what you should be doing is opening a NotesView object using the NotesDatabase.getView() method, and then use the NotesView.getDocumentByKey() method to get the document for the user. E.g., something like this:
NotesView usersView = namesDb.getView("$Users");
NotesDocument userDoc = usersView.getDocumentByKey(employeeId);
Then just read the data that you want, using userDoc.getItemValue() for each information field that you are interested in. You should only do a loop through the entire userdoc.Items array if you are really trying to capture everything, including a bunch of internal-use values.
I have need to select a number of 'master' rows from a table, also returning for each result a number of detail rows from another table. What is a good way of achieving this without multiple queries (one for the master rows and one per result to get the detail rows).
For example, with a database structure like below:
MasterTable:
- MasterId BIGINT
- Name NVARCHAR(100)
DetailTable:
- DetailId BIGINT
- MasterId BIGINT
- Amount MONEY
How would I most efficiently populate the data object below?
IList<MasterDetail> data;
public class Master
{
private readonly List<Detail> _details = new List<Detail>();
public long MasterId
{
get; set;
}
public string Name
{
get; set;
}
public IList<Detail> Details
{
get
{
return _details;
}
}
}
public class Detail
{
public long DetailId
{
get; set;
}
public decimal Amount
{
get; set;
}
}
Normally, I'd go for the two grids approach - however, you might also want to look at FOR XML - it is fairly easy (in SQL Server 2005 and above) to shape the parent/child data as xml, and load it from there.
SELECT parent.*,
(SELECT * FROM child
WHERE child.parentid = parent.id FOR XML PATH('child'), TYPE)
FROM parent
FOR XML PATH('parent')
Also - LINQ-to-SQL supports this type of model, but you need to tell it which data you want ahead of time. Via DataLoadOptions.LoadWith:
// sample from MSDN
Northwnd db = new Northwnd(#"c:\northwnd.mdf");
DataLoadOptions dlo = new DataLoadOptions();
dlo.LoadWith<Customer>(c => c.Orders);
db.LoadOptions = dlo;
var londonCustomers =
from cust in db.Customers
where cust.City == "London"
select cust;
foreach (var custObj in londonCustomers)
{
Console.WriteLine(custObj.CustomerID);
}
If you don't use LoadWith, you will get n+1 queries - one master, and one child list per master row.
It can be done with a single query like this:
select MasterTable.MasterId,
MasterTable.Name,
DetailTable.DetailId,
DetailTable.Amount
from MasterTable
inner join
DetailTable
on MasterTable.MasterId = DetailTable.MasterId
order by MasterTable.MasterId
Then in psuedo code
foreach(row in result)
{
if (row.MasterId != currentMaster.MasterId)
{
list.Add(currentMaster);
currentMaster = new Master { MasterId = row.MasterId, Name = row.Name };
}
currentMaster.Details.Add(new Detail { DetailId = row.DetailId, Amount = row.Amount});
}
list.Add(currentMaster);
There's a few edges to knock off that but it should give you the general idea.
select < columns > from master
select < columns > from master M join Child C on M.Id = C.MasterID
You can do it with two queries and one pass on each result set:
Query for all masters ordered by MasterId then query for all Details also ordered by MasterId. Then, with two nested loops, iterate the master data and create a new Master object foreach row in the main loop, and iterate the details while they have the same MasterId as the current Master object and populate its _details collection in the nested loop.
Depending on the size of your dataset you can pull all of the data into your application in memory with two queries (one for all masters and one for all nested data) and then use that to programatically create your sublists for each of your objects giving something like:
List<Master> allMasters = GetAllMasters();
List<Detail> allDetail = getAllDetail();
foreach (Master m in allMasters)
m.Details.Add(allDetail.FindAll(delegate (Detail d) { return d.MasterId==m.MasterId });
You're essentially trading memory footprint for speed with this approach. You can easily adapt this so that GetAllMasters and GetAllDetail only return the master and detail items you're interested in. Also note for this to be effective you need to add the MasterId to the detail class
This is an alternative you might consider. It does cost $150 per developer, but time is money too...
We use an object persistence layer called Entity Spaces that generates the code for you to do exactly what you want, and you can regenerate whenever your schema changes. Populating the objects with data is transparent. Using the objects you described above would look like this (excuse my VB, but it works in C# too):
Dim master as New BusinessObjects.Master
master.LoadByPrimaryKey(43)
Console.PrintLine(master.Name)
For Each detail as BusinessObjects.Detail in master.DetailCollectionByMasterId
Console.PrintLine(detail.Amount)
detail.Amount *= 1.15
End For
With master.DetailCollectionByMasterId.AddNew
.Amount = 13
End With
master.Save()