Gridview with Dictionary - asp.net

I've created a Dictionary like
Dictionary<Department,bool> dict= new Dictionary<Department,bool>();
here Department is a class and I have Id,Name and Code for the departments. And in the bool am sending whether the person is HOD or not.
Am adding the records to this Dictionary like
dict.Add(department,chkHOD.checked);
here the records are successfully added to the Dictionary and after this am binding the Dictionary to a GridView like
gridDept.Datasource=dict;
gridDept.Databind();
now the inserted records are displayed fine in the gridview. After this am storing this records in the 'StaffDepartments' table in my database. I have 3 columns in the 'Staffdepartments' table
1.StaffId(PK - has link with the Staff table)
2.DepartmentId(PK - has link with the Department table)
3.IsHOD.
here the records are stored fine in the database.No problem in adding the records into the database.
I have some questions here
*1.How can check whether the DepartmentId is already there in the Dictionary before adding to it.
2.When am editing the staff detail how can I delete the Selected Department from the Dictionary by checking the checkbox in Gridview rows.(here the records are coming from the database, so when I click delete button the records should be deleted in the database as well)*
if its a List instead of Dictionary, I can get the DepartmentId by
int departmentId = (int)gridDept.DataKeys[row.RowIndex].Values["DepartmentId"];
but in Dictionary i dunno how to do the same with Key and Value pairs....can anyone help me here.

How can check whether the DepartmentId is already there in the
Dictionary before adding to it.
You could use this:
if (!dict.Keys.Any(d => d.DepartmentId == department.DepartmentId))
dict.Add(department,chkHOD.checked);
But something is wrong here. If your real key is the DepartmentId and not the Department (object identity) you should make it the key in the dictionary. For example, you could define a helper class:
public class DepartmentBindingHelper
{
public int DepartmentId { get; set; }
public Department Department { get; set; }
public bool Checked { get; set; }
}
An then define a dictionary like this:
var dict = new Dictionary<int, DepartmentBindingHelper>();
And add the objects this way to the dictionary:
if (!dict.ContainsKey(department.DepartmentId))
dict.Add(department.DepartmentId, new DepartmentBindingHelper
{
DepartmentId = department.DepartmentId,
Department = department,
Checked = chkHOD.checked
});
Then you can bind only the value collection to the grid:
gridDept.Datasource = dict.Values;// it's an IEnumerable<DepartmentBindingHelper>
gridDept.Databind();
And your code to retrieve the DepartmentId from a row would work without changes:
int departmentId = (int)gridDept.DataKeys[row.RowIndex].Values["DepartmentId"];

Related

Create DB trigger to Sql DB

Im new to DB stuff and I need to create DB trigger to azure SQL DB.
I've create MVC5 project with model first and I have this model which reflect the DB table.
public class Employee
{
public int Id { get; set; }
public string EmployeeName { get; set; }
public string EmpAddress { get; set; }
public string EmpEmail { get; set; }
public string EmpPhone { get; set; }
}
public class EmployeeDbContext : DbContext
{
public EmployeeDbContext()
: base("DefaultConnection")
{
}
public DbSet<Employee> EmployeeCollection { get; set; }
}
}
Now I want to create DB trigger for it and I try like following.(I take this example from SO and adjust it...)
Create Trigger Dbo.triggerName ON Employee
AFTER INSERT, Update, Delete
AS Begin
-- Log Deleted Rows and Old Value
Insert Into EmployeeCopy(Id ,EmployeeName, EmpAddress,EmpEmail,EmpPhone)
Select CURRENT_EMPLOYEE, Columns
From Deleted
-- Log Inserted Row and New Value
Insert Into EmployeeCopy(Id ,EmployeeName, EmpAddress,EmpEmail,EmpPhone)
Select CURRENT_EMPLOYEE, Columns
From Inserted
End
I want it to create new table which is EmployeeCopy and copy all the rows to it.
so this is my question (I new to this topic)
1. what is the trigger name?
2.Do I write the Insert into right ?
3. Select CURRENT_EMPLOYEE, Columns ..Here Im not sure if this is the right way to write it?
Your insert into statement may be changed (see below) - but you did not specify condition of your select => you will probably insert all rows from your deleted and Inserted tables on each trigger operation.
See more details about insert into, for example, here.
You should probably write and test your select statement as stand-alone query (just run it from New Query window), When you'll get expected results - put it in the trigger's logic.
Generally, I'll suggest to try each part of your trigger logic as stand-alone statements.
Create Trigger dbo.MyTrigger ON Employee
AFTER INSERT, Update, Delete
AS Begin
-- Log Deleted Rows and Old Value
Insert Into EmployeeCopy
Select (Id ,CURRENT_EMPLOYEE, EmpAddress,EmpEmail,EmpPhone)
From Deleted
WHERE Your_conditions_logic_here
-- Log Inserted Row and New Value
Insert Into EmployeeCopy
Select (Id ,CURRENT_EMPLOYEE, EmpAddress,EmpEmail,EmpPhone)
From Inserted
WHERE Your_conditions_logic_here
End

XtraGrid checkEdit repository could not be checked/unchecked

I've devexpress XtraGrid populated with data using linq/LinqInstantFeedbackSource. The XtraGrid has a checkEdit repository bind with a column named Status from a table. The data elements in Status column are bits (0 or 1). However, for some unknown reason, the checkEdit could not be selected - i.e. I can't check/uncheck it. What could be the possible reason??
The reason is that the LinqInstantFeedbackSource is a read-only data source.
UPDATE:
As far as I can see you are using the anonymous type as result. Objects of the anonymous type have only read-only properties. It's impossible to modify them. That's why there are no editing in XtraGrid. If you need to obtain a collection of editable objects, don't use anonymous types.
You can use this code, for example:
var tcs=
from tc in dc.TC
join dpt in dc.Departments on tc.DeptID equals dpt.DeptID
where tc.isReturned.Equals(0)
select new EditableObject {
MRN=tc.MRN,
DeptName=dpt.deptName + " - " + dpt.roomNo,
IsReturned= tc.isReturned
};
where EditableObject is:
public class EditableObject{
public string MRN { get; set; }
public string DeptName { get; set; }
public bool IsReturned { get; set; }
}

ViewModel: how to display values from datatable in List View

I have created a viewmodel class for my custom page. I have a stored procedure which returns the DataTable(ORM tool). I cannot change this procedure. But I would like display the records from the stored procedure on View List. How can I display the values from the datatable in the List View? I appreciate any help.
Thanks,
public class CreateViewModel
{
[Required]
public DateTime StartDate {get; set;}
[Required]
[StringLength(250, ErrorMessage = "Details must be less than 250 characters")]
public string Details { get; set; }
}
The main way of doing it would be reading out the column values from each row of the datatable into the view model instance. This is regular DataTable access way. This should be done in your service layer called from your controller action.
If you can't change the stored proc, but are not tied to a DataTable then if you execute the SqlCommand to return a SqlReader. Then you can access the data with the following code (something like):
var list = new List<MyViewData>();
while(reader.Read())
{
var model = new MyViewData();
model.Property = reader.GetString(reader.GetOrdinal("ColumnName"));
// .. etc..
list.Add(model);
}
return list;
This accesses the recordset returned from the stored proc.
You can then set your view's model property as an IEnumerable then you can access each of the instances with a foreach over the model in the view.
Hope this helps.

How do you bind a linq-to-entities query that contains a join to a writable datagridview?

This question, although similar to others, doesn't seem to be a duplicate. If it is, please clarify and I will be happy to merge.
I want to bind to a writable DataGridView using a linq-to-entities query containing a join. The model is as follows:
The denormalized DataGridView should be bound like so:
The following code binds but results in a readonly DataGridView because the linq-to-entities query returns an anonymous type (see this post). I'm at an impasse because I think I need the anonymous type to do the denormalization.
var query = from t in iDictionaryContext.DisplayTexts
from l in iDictionaryContext.Languages
where
t.LanguageID == l.LanguageID
select new
{
Key = t.DisplayKey,
Text = t.DisplayText1,
Language = l.LanguageName
};
I also tried the solution suggested here but it seems to apply to linq-to-sql but not to linq-to-entities. When setting the bindingsource.datasource to the linq-to-entities query, an exception is thrown reading "Only parameterless constructors and initializers are supported in LINQ to Entities."
Thank you for your advice,
Tim
Just define presentation type like that. You don't have to pass objects in constructor:
public class LanguageDisplayTextPresentation
{
public int Key { get; set; }
public string Text { get; set; }
public string Language { get; set; }
}
and then
var query = from t in iDictionaryContext.DisplayTexts
from l in iDictionaryContext.Languages
where
t.LanguageID == l.LanguageID
select new LanguageDisplayTextPresentation
{
Key = t.DisplayKey,
Text = t.DisplayText1,
Language = l.LanguageName
};

problem with asp.net gridview

I have problem with gridview deleting.I have table name Doctor with
Id,Name,Address,Phone.Id is auto generated field.After adding data
when i am displaying in gridview then if delete any id from gridview
Again then if i add any new details from the form its starting from
the new number.I mean if i delete the last id no 5 then again if i
add any new doctor its taking id value 6 not from 5.My query is it
should start again from 5.Here is my code.Pls help me.
public class Doctor
{
public int Id { get; set; }
public string Name { get; set; }
public string Address { get; set; }
public string Phone { get; set; }
}
public static class DoctorDataLayer
{
public static void AddDoctor(Doctor doctor)
{
string connectionString = ConfigurationManager.ConnectionStrings["ConnectionString"].ConnectionString; // JohannesH: Changed from .ToString() to .ConnectionString
using(var connection = new SqlConnection(connectionString))
{
using (var command = new SqlCommand("insert into doctor values(#name,#address,#phone)", connection))
{
command.Parameters.AddWithValue("#name", doctor.Name);
command.Parameters.AddWithValue("#address", doctor.Address);
command.Parameters.AddWithValue("#phone", doctor.Phone);
connection.Open();
command.ExecuteNonQuery();
connection.Close();
}
}
}
}
public static class DoctorBusinessLayer
{
public static void CreateDoctor(string name, string address, string phone)
{
DoctorDataLayer.AddDoctor(new Doctor {Name = name, Address = address, Phone = phone});
}
}
This is perfectly normal database behaviour and has nothing to do with your GridView. If you have an issue with gaps in autogenerated (identity) columns, either use your own logic to generate unique ID's or use custom SQL scripts to check for gaps in Identity values and fill those gaps.
Example B in the Transact-SQL reference shows a way to do just this.
So the Id is created by the database (autonumber). When id 5 is used it's used up. This is normal behavior.
As other have noted, if this is an autogenerated ID from the DB then once it is used it will not be regenerated, each ID is unique regardless if the data still exists or not. If IDs were recycled you could get into issues with foreign references that may have pointed to the old item with that ID and now would point to a new different record with the reused ID.
Typically you don't expose the IDs to the user anyway so it is a non issue.
You shouldn't depend on autogenerated ids sequences being ordered or not having gaps. As others have noted, the behavior you are seeing is perfectly normal behavior for an autogenerated id and to make it otherwise you'll need to jump through a lot of hoops. If you need the ids to be ordered by the insertion sequence, you should put in an autogenerated date/time field and then select the data ordered by that field (and index it). That way if you ever decide to switch from a numeric id to a GUID or some other id format in which the sort order is different than the insertion order your data will still be ordered correctly. If you need to have a "place order" for each, generate that automatically (say a rownumber) as you are selecting ordered by date. That way you will still have strict numerical ordering even if records get deleted later.

Resources