I have just started with my project using MVC and Razor. Now I am encountering a problem when it comes to binding data coming from the database to a dropdownlist. Please refer on my codes below:
Specialization Model:
public class SpecializationModel
{
[Display(Name = "SpecializationID")]
public string SpecializationID { get; set; }
[Display(Name = "SpecializationDescription")]
public string SpecializationDescription { get; set; }
public IEnumerable<SelectListItem> Items { get; set; }
public int SelectedSpecializationID { get; set; }
}
Controller:
public ActionResult Physicians()
{
SpecializationManager spec = new SpecializationManager();
List<Specialization> SpecializationList = spec.GetAllSpecialization();
var obj = new SpecializationModel();
obj.Items = new[]
{
foreach(var x in SpecializationList)
{
new SelectListItem { Value = x.SpecializationID.ToString(), Text = x.SpecializationDescription };
}
};
return View(obj);
}
I have this manager which contains my LINQ query to extract the data from the database.
I encounter problems on the controller. Wherein the error points on the foreach syntax saying Invalid expression term foreach
Can anyone please point me to the right direction? Thanks a lot!
EDIT:
I have this code now without errors on the foreach part (thanks to the post below which I combined with what I have above). However, I can't seem to make the last line work. It produces an error about implicit cast:
var items = new List<SelectListItem>();
foreach (var x in SpecializationList)
{
items.Add(new SelectListItem { Value = x.SpecializationID.ToString(), Text = x.SpecializationDescription });
}
obj.Items = items.ToList();
Please do help me. Thanks :)
yopu can't put a foreach in a constructor, try:
var items = new List<SelectListItem >();
foreach(var x in SpecializationList)
{
items.add(new SelectListItem { Value = x.SpecializationID.ToString(), Text = x.SpecializationDescription });
}
obj.Items = items;
Edited
Related
Hello I have a strange issue here. I have a Project model that has a foreign key to the Company model. The thing is that when I attach my Project property in order to update it, then it updates all other primitive fields, except for the Company.
The Project model looks like this:
public class Project
{
[Key]
public int ID { get; set; }
[Index(IsUnique = true)]
public string Name { get; set; }
public virtual Company Company { get; set; }
public bool ExportProjectName { get; set; }
public DateTime CreatedAt { get; set; }
}
Then what I do, is I have a ProjectsViewModel, that gets all Projects from the Database. I wrap each of them then in a ProjectViewModel which exposes some fields of the Project and also has a saving method. I think the ProjectsViewModel implementation may not be that important so I'll paste only the two lines that populate the ProjectViewModels:
var projects = dbcontext.Projects.Include(x => x.Company).ToList().Select(x => new ProjectViewModel(x));
this.ListOfProjects = new ObservableCollection<ProjectViewModel>(projects);
Then I have the ProjectViewModel. Take a look at the SaveProject method:
public class ProjectViewModel : INotifyPropertyChanged
{
private Project _project;
public Project Project
{
get { return _project; }
set
{
_project = value;
NotifyPropertyChanged("Project");
}
}
public int ID
{
get { return Project.ID; }
set
{
Project.ID = value;
NotifyPropertyChanged("ID");
}
}
public string Name
{
get { return Project.Name; }
set
{
Project.Name = value;
NotifyPropertyChanged("Name");
}
}
public Company Company
{
get { return Project.Company; }
set
{
Project.Company = value;
NotifyPropertyChanged("Company");
}
}
public ProjectViewModel(Project project)
{
this.Project = project;
}
public void SaveProject()
{
using (DbContext dbcontext = new DbContext())
{
// At this state this.Project and this.Company exist in the database
dbcontext.Companies.Attach(this.Company);
dbcontext.Projects.Attach(this.Project);
dbcontext.Entry(this.Project).State = EntityState.Modified;
dbcontext.SaveChanges();
}
}
public event PropertyChangedEventHandler PropertyChanged;
protected void NotifyPropertyChanged(String info)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(info));
}
}
And that's it. I have the SaveProject bound to a command, which I just trigger.
And then in the logs I can only see such a query:
Opened connection at 08/12/2018 17:47:21 +01:00
Started transaction at 08/12/2018 17:47:21 +01:00
UPDATE "public"."Projects" SET "Name"=#p_0,"ExportProjectName"=#p_1,"CreatedAt"=#p_2 WHERE "ID" = #p_3
So all properties are there, except for the Company. If that's important - I'm using PostgreSQL with NpgSql. I saw many question on SO in regards to the related object not being updated itself, but I couldn't find any question where the relation would be only broken. Hope somebody can help!
EDIT:
BTW the code below would work, but I do not want to assign all properties by myself and would want to avoid getting the object from the DB one more time. And I want to know, why the relation is not updated in the first case, as it doesn't make sense for me.
dbcontext.Companies.Attach(this.Company);
var p = dbcontext.Projects.Single(x => x.ID == this.ID);
p.Name = this.Name;
p.Company = this.Company;
dbcontext.SaveChanges();
This is my object structure
class object
{
string projectname;
string projectid;
list<string> associated_students;
}
//The List I am binding to the grid
list<objects> objectList = getList();
dataGridView.Source =objectList;
Now I want to bind the combo box inside the datagrid with the list "associated_students"
If I understand the question, you want each row to be tied to an object within your list of objects and you want the third column to show a combobox of that object's unique list of associated students. If I am correct, a simple search leads to this similar question:
How do I set up a DataGridView ComboBoxColumn with a different DataSource in each cell?
To solve, you need to manually bind each row. I was able to duplicate your problem and came up with this solution:
Your class "object"
public class Assignment
{
public Assignment()
{
this.Associated_Students = new List<string>();
}
public string ProjectName { get; set; }
public string ProjectID { get; set; }
public List<string> Associated_Students { get; set; }
}
And in Form1:
public Form1()
{
InitializeComponent();
this.Assignments = new List<Assignment>()
{
new Assignment()
{
ProjectID = "1",
ProjectName = "First",
Associated_Students = new List<string>() { "Me", "You", "Him", "Her" }
},
new Assignment()
{
ProjectID = "2",
ProjectName = "Second",
Associated_Students = new List<string>() { "Foo", "Bar" }
}
};
this.BindDGViewToList();
}
public List<Assignment> Assignments { get; set; }
public void BindDGViewToList()
{
DataGridViewTextBoxColumn col1 = new DataGridViewTextBoxColumn();
col1.Name = "Project Name";
col1.ValueType = typeof(string);
dataGridView1.Columns.Add(col1);
DataGridViewTextBoxColumn col2 = new DataGridViewTextBoxColumn();
col2.Name = "Project ID";
col2.ValueType = typeof(string);
dataGridView1.Columns.Add(col2);
DataGridViewComboBoxColumn col3 = new DataGridViewComboBoxColumn();
col3.Name = "Associated Students";
col3.ValueType = typeof(string);
dataGridView1.Columns.Add(col3);
for (int i = 0; i < this.Assignments.Count; i++)
{
DataGridViewRow row = (DataGridViewRow)(dataGridView1.Rows[0].Clone());
DataGridViewTextBoxCell textCell = (DataGridViewTextBoxCell)(row.Cells[0]);
textCell.ValueType = typeof(string);
textCell.Value = this.Assignments[i].ProjectName;
textCell = (DataGridViewTextBoxCell)(row.Cells[1]);
textCell.ValueType = typeof(string);
textCell.Value = this.Assignments[i].ProjectID;
DataGridViewComboBoxCell comboCell = (DataGridViewComboBoxCell)(row.Cells[2]);
comboCell.ValueType = typeof(string);
comboCell.DataSource = this.Assignments[i].Associated_Students;
dataGridView1.Rows.Add(row);
}
}
Note: This will display what you are asking for but you will have to handle updating your data. I would suggest researching BindingList over List objects. There may be better solutions, but this worked quickly for me.
I am getting result from theee tables usign linq to sql but i am unable to use the values in the view, how i can do that as i am new to mvc
here is my controller code:
public ActionResult Grid()
{
ViewBag.Message = "Your Grid page.";
bc_limsEntities objbc_limsDBContext = new bc_limsEntities();
var result = from b in objbc_limsDBContext.dc_tpatient_bookingm
join d in objbc_limsDBContext.dc_tpatient_bookingd on b.bookingid equals d.bookingid
join t in objbc_limsDBContext.dc_tp_test on d.testid equals t.TestId
where b.bookingid == 41239 && d.ProcessID == 0006 && t.SubdepartmentId == 16
select new {b.bookingid,
d.bookingdid,
d.testid,
t.Test_Name,
t.procedureid,
t.ClinicalUse,
t.AutomatedText};
ViewBag.Result = result.ToList();
return View(result);
}
and I am doing like this in view:
#foreach(var item in ViewBag.Result)
{
<h1>#item</h1>
}
I solved my self by this way:
public class ResultSet
{
public long bookingid { get; set; }
public long bookingdid { get; set; }
public long testid { get; set; }
public string Test_Name { get; set; }
public long procedureid { get; set; }
public string ClinicalUse { get; set; }
public string AutomatedText { get; set; }
}
and in Controller:
bc_limsEntities objbc_limsDBContext = new bc_limsEntities();
var result = from b in objbc_limsDBContext.dc_tpatient_bookingm
join d in objbc_limsDBContext.dc_tpatient_bookingd on b.bookingid equals d.bookingid
join t in objbc_limsDBContext.dc_tp_test on d.testid equals t.TestId
where b.bookingid == 41239 && d.ProcessID == 0006 && t.SubdepartmentId == 16
select new {b.bookingid,
d.bookingdid,
d.testid,
t.Test_Name,
t.procedureid,
t.ClinicalUse,
t.AutomatedText};
List<ResultSet> resultList = new List<ResultSet>();
foreach (var temp in result)
{
ResultSet objResultSet = new ResultSet();
objResultSet.bookingid = temp.bookingid;
objResultSet.bookingdid = temp.bookingdid;
objResultSet.testid = temp.testid;
objResultSet.Test_Name = temp.Test_Name;
objResultSet.procedureid = long.Parse(temp.procedureid.ToString());
objResultSet.ClinicalUse = temp.ClinicalUse;
objResultSet.AutomatedText = temp.AutomatedText;
resultList.Add(objResultSet);
}
ViewBag.Result = resultList;
return View(resultList);
and in View like this:
#foreach(var item in Model)
{
<tr>
<td class="t_center"><input type="checkbox" id="c14" name="cc" /><label for="c14"><span></span></label></td>
<td>#item.bookingid</td>
<td>#item.bookingdid</td>
<td>#item.testid</td>
<td>#item.Test_Name</td>
<td>#item.procedureid</td>
<td>#item.ClinicalUse</td>
<td>#item.AutomatedText</td>
</tr>
}
Don't use the View bag, use a View Model. You are already passing results as the View Model in this case, so you need to declare the model at the top of your view page, like so:
#model List<Item>
(or whatever type of object results is)
Then you can use it like this:
#foreach(var item in Mode)
{
<h1>#item.Property</h1>
}
Normally, you would have a dedicated View Model class that contains a number of properties, one of which would be your results list, try that instead if you are feeling adventurous!
EDIT: Because you are dynamically creating a custom object you wont know the type, what you should do is create a class (e.g. Item) that has all the fields you need, and then populate that class from your three tables, then use that.
How about trying something like:
#foreach(var item in ViewBag.Result)
{
<h1>#item.bookingid</h1>
}
if of course you wanna stick with using the viewbag but otherwise musefan's suggestion of using a view model is much cleaner and what you should really be doing.
public class ConvertedReading
{
public int DatePointID { get; set; }
public string DatapointName { get; set; }
public DateTime ReadingDate { get; set; }
public double Value { get; set; }
}
Given a collection below:
IEnumerable<ConvertedReading> readingData;
using c# , write a LINQ statment using lambda syntax to output a collection of the following:
public class DataPointTotal
{
public string DatapointName{get; set;}
public double Total{get; set;}
}
one item should be returned per datepointID
Total should reprenst the sum of convertedReading.valye relevent to each datePointID
I have tried with the following, nit quite shre if it works, i cant seems to get the sum of value right.
var subtotals = from x in ConvertedReading group x by x.DatapointName into g select new { Type = x.DatapointName , SubTotal = g.Sum(x => x.Total) };
Is the syntax correct?
Thanks guys,
The answer is:
var result = readingData.GroupBy(r => r.DataPointID)
.Select(g => new DataPointTotal
{
DataPointName = g.First().DataPointName,
Total = g.Sum(r => r.Value)
});
But I guess that's cheating considering I wrote the question! ;)
var result = db.ConvertedReading.GroupBy(i=>i.DatapointName).Select(g => new DataPointTotal(){DatapointName = g.DatapointName, Total = g.Sum(i=>i.Total)});
I am pretty new to Dapper Rainbow so I may be missing something obvious. Is it possible to specify the table name and if so how?
I have tried the following with no luck.
public class DashboardContext : Database<DashboardContext>
{
public DashboardContext()
{
this.DashboardResults = new Table<DashboardResult>(this, "Monitor.DashboardResult");
}
public Table<DashboardResult> DashboardResults { get; set; }
}
I had the same problem but it seems an error in the code. I´ve just commented the lines where is setting the constructor for tables (Database.cs) and it works.
internal void InitDatabase(DbConnection connection, int commandTimeout)
{
this.connection = connection;
//this.commandTimeout = commandTimeout;
//if (tableConstructor == null)
//{
// tableConstructor = CreateTableConstructorForTable();
//}
//tableConstructor(this as TDatabase);
}
I guess this is not the best solution...
You need to hack the rainbow source to get it to work.
Find the CreateTableConstructor method in the file of DataBase.cs.
Just add some code as following:
...
var setters = GetType().GetProperties()
.Where(p => p.GetValue(this, null) == null
&& p.PropertyType.IsGenericType
&& p.PropertyType.GetGenericTypeDefinition() == tableType)
.Select...
For anyone else stumpeling over this post like I did this is now fixed in Dapper.Rainbow version 0.1.3.
It is still in beta at this time (0.1.3-beta1) so if you want to use schema you can clone/fork the repository and run the build script. The binary output can then be used directly or packaged.
As for the table setup you need to define the table name with the name of the schema for for that particular table so for example looking at this example without schema
public class MyDatabase : Database<MyDatabase>
{
public Table<Order> Order{ get; set; }
public Table<Customer> Customer { get; set; }
public Table<Item> Item { get; set; }
}
Which works if you are only using dbo. but if you are for instance using say Product schema for Item you would have to define it using a constructor
public class MyDatabase : Database<MyDatabase>
{
public Table<Order> Order{ get; set; }
public Table<Customer> Customer{ get; set; }
public Table<Item> Item;
public MyDatabase()
{
Item = new Table<Item>(this, "Product.Item");
}
}
The rest should be as before
using (var connection = DbConnections.Create())
{
connection.Open();
var db = MyDatabase.Init((DbConnection)connection, commandTimeout: 2);
var insert = db.Customer.Insert(
// .
//..... your object
// .
);
var insertId = insert.Value;
}
Based on #Acorax answer, it wasn't enough for me, I needed to add brackets to the schema and table name to solve this.
So this solved me the schema problem:
public class MyDatabase : Database<MyDatabase>
{
public Table<Item> Items;
public HamenasDbSchema()
{
Items = new Table<User>(this, "[Schema].[Items]");
}
}