this is my first post, hopefully I'm following the rules!
After a few weeks of banging my head against brick walls and endless hours of internet searches, I have decided I need to make my own post and hopefully find the answers and guidance from all you experts.
I am building an ASP.NET application (in Visual Studio 2010) which uses an SQL 2008 database and Entity Framework 4 to join the two parts together. I designed the database as a database project first, then built the Entity Model as a class project which is then referenced in the main ASP.NET project. I believe this is called Database First in Entity Framwork terms?
I'm fairly new to Web Apps (I mainly develop WinForms apps) and this is my first attempt at using Entity Framwork.
I can just about understand C# so any code samples or snippets you might supply would be preferred in VB if possible.
To give some background on where I am so far. I built a regsitration page called register.aspx and created a wizard style form using ASP:Wizard with ASP:TextBox, ASP:DropdownList and ASP:CheckBoxList it's all laid out inside a HTML table and uses CSS for some of the formatting. Once the user gets the the last page in the wizard and presses "Finish" I execute some code in the VB code behind file as follows:
Protected Sub wizardRegister_FinishButtonClick(sender As Object, e As System.Web.UI.WebControls.WizardNavigationEventArgs) Handles wizardRegister.FinishButtonClick
Dim context As New CPMModel.CPMEntities
Dim person As New CPMModel.Person
Dim employee As New CPMModel.Employee
Dim newID As Guid = Guid.NewGuid
With person
.ID = newID
.UserID = txbx_UserName.Text
.Title = ddl_Title.SelectedValue
.FirstName = txbx_FirstName.Text
.MiddleInitial = txbx_MiddleInitial.Text
.FamilyName = txbx_FamilyName.Text
.Gender = ddl_Gender.SelectedValue
.DOB = txbx_DOB.Text
.RegistrationDate = Date.Now
.RegistrationMethod = "W"
.ContactMethodID = New Guid(ddl_ContactMethodList.SelectedValue)
.UserName = txbx_UserName.Text
If Not (My.Settings.AuthenticationUsingAD) Then
.Password = txbx_Password.Text ' [todo] write call to salted password hash function
End If
.IsRedundant = False
.IsLocked = False
End With
context.AddToPeople(person)
With employee
.ID = newID
.PayrollNumber = txbx_PayrollNumber.Text
.JobTitle = txbx_JobTitle.Text
.DepartmentID = ddl_DepartmentList.SelectedValue
.OfficeNumber = txbx_OfficeNumber.Text
.HomeNumber = txbx_HomeNumber.Text
.MobileNumber = txbx_MobileNumber.Text
.BleepNumber = txbx_BleepNumber.Text
.OfficeEmail = txbx_OfficeEmail.Text
.HomeEmail = txbx_HomeEmail.Text
.IsRedundant = False
.RedundantDate = Nothing
'--------------------------
.FiledBy = Threading.Thread.CurrentPrincipal.Identity.Name
.FiledLocation = My.Computer.Name
.FiledDateTimeStamp = Date.Now
'----------------------------
End With
context.AddToEmployees(employee)
context.SaveChanges()
End Sub
The above works fine, seemed to be a sensible way of doing it (remember I'm new to Entity Framework) and gave me the results I extpected.
I have another page called manage.aspx on this page is a tab control, each tab page contains a asp:DetailsView which is bound to an asp:EntityDataSource, I have enabled Update on all the Entity Data Sources and on some I have also enabled Insert, none of the have delete enabled.
If I build and run the app at this stage everything works fine, you can press the "edit" link make changes and then press "update" and sure enough those updates are displayed on the screen instantly and the database does have the correct values in.
Here's the problem, I need to intercept the update in the above code (the bold bit) notice there is a column in my database called FiledBy, FiledLocation, and FiledDateTimeStamp. I don't want to show these columns to the user viewing the ASP.NET page but I want to update them when the user presses update (if there were any changes made). I have tried converting the ASP:DetailsView into a template and then coding the HTML side with things like;
<@# Eval(User.Name) #>
I did manage to get it to put the correct values in the textboxes when in edit mode but I had the following problems;
- It didn't save to the database
- I have to show the textboxes which I don't want to do
I have read on several other posts on here and other websites that you can override the SaveChanges part of the Entity Framwork model one example of this is in the code below;
public override int SaveChanges()
{
var entities = ChangeTracker.Entries<YourEntityType>()
.Where(e => e.State == EntityState.Added)
.Select(e => e.Entity);
var currentDate = DateTime.Now;
foreach(var entity in entities)
{
entity.Date = currentDate;
}
return base.SaveChanges();
}
The problem is, that whilst I understand the idea, and can just about transalate it to VB I have no idea how to implement this. Where do I put the code? How do I call the code? etc.
I would ideally like to find a solution that meets the following requirements:
- Doesn't get overwritten if I was to regenerate / update the Entity Model
- Doesn't need to be copy and pasted for every table in my model (most but not all have the audit columns in)
- Can be used for other columns, for example, if a user make a selection in a check list I may want to write some value into another (not exposed to the user) column.
Am I taking the right approach to displaying data in may webpages I certainly find the DataView and GridView limiting, I did think about creating a form like the registration form in table tags but have no Idea how to populate the textboxes etc with values from the database nor how to implement paging as many of the tables have one to many relationships, although saving changes would be easy if I did populate textboxes on a table.
Thank you all in advance to anyone who offers there support.
Kevin.
Ok so I have now got closer, but still not got it working correctly. I've used the following code to edit the value in the DetailsView on the Databound event. If writes the correct timestamp into the read only textbox but does not right this value back to the database when you press the Update button on the DetailsView control.
Protected Sub dv_Employee_DataBound(sender As Object, e As EventArgs) Handles dv_Employee.DataBound
If dv_Employee.CurrentMode = DetailsViewMode.Edit Then
For Each row In dv_Employee.Rows
If row.Cells(0).Text = "FiledDateTimeStamp" Then
row.Cells(1).Text = Date.Now()
End If
Next
End If
End Sub