I am using Entity Framework to link my data to asp.net mvc application.
The weird part is that I can read the records normally using the below GetALL function but none of the Insert and Delete are working. Is there any reason for that? I am wondering if there is any restriction on the database and how to fix it if any? Note that I am getting no error however it is saying create is successful and delete is successful as well.
public IEnumerable<tbl_Category> GetALL()
{
return db.tbl_Category.ToList();
}
public tbl_Category GetByID(int Id)
{
return db.tbl_Category.Find(Id);
}
public void Insert(tbl_Category cat)
{
db.tbl_Category.Add(cat);
}
public void Delete(int Id)
{
tbl_Category cat = db.tbl_Category.Find(Id);
db.tbl_Category.Remove(cat);
}
I think you have to call the SubmitChanges() / SaveChanges() on the data context.
Related
I have a table with a DATETIME DEFAULT field.
CREATE TABLE People
(
Id INT NOT NULL IDENTITY(1,1) PRIMARY KEY,
Name VARCHAR(100) NOT NULL,
...
DtOccurrence DATETIME DEFAULT getDATE(),
);
Using scaffolding for generate Class and Entitity for Controllers + Views.
Default CRUD working fine, but if I try update a register, [DtOccurrence] get NULL in database.
How fix it? Thanks in advance
Create saving OK
Update only [Name] field send null [DtOccurrence] for database and my auto-generated class dont have this [DtOccurrence] field:
UPDATE:
CONTROLLER Create method
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Create([Bind("Id,Name")] People people)
{
if (ModelState.IsValid)
{
_context.Add(people);
await _context.SaveChangesAsync();
return RedirectToAction("Edit", "Pessoas", new { people.Id });
}
return View(people);
}
CONTROLLER Edit method
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Edit(int id, [Bind("Id,Name,")] People people)
{
if (id != people.Id)
{
return NotFound();
}
if (ModelState.IsValid)
{
try
{
_context.Update(people);
await _context.SaveChangesAsync();
}
catch (DbUpdateConcurrencyException)
{
if (!PeopleExists(people.Id))
{
return NotFound();
}
else
{
throw;
}
}
return RedirectToAction(nameof(Index));
}
return View(people);
}
Auto-generated class scaffolding
public partial class Pessoa
{
public Pessoa()
{
public int Id { get; set; }
public string Name { get; set; }
}
}
As mentioned in my comment, while your initial request to provide data to the view was given an entity from the DB Context, the object (Person) you get back in your Update method is not the same entity, and is not associated with your DbContext. It is a deserialized copy. Calling Update with it when it does not contain all fields will result in fields getting set to #null. Calling Update with a detached entity like this from a client is also an attack vector for unauthorized updates to your domain. (Debugging tools /plugins can intercept the call to the server and alter the entity data in any number of ways.)
public async Task<IActionResult> Edit(int id, [Bind("Id,Name,")] People people)
{
if (!ModelState.IsValid)
return View(people);
var dataPeople = await _context.People.SingleAsync(x => x.id == people.id);
dataPeople.name = people.name;
await _context.SaveChangesAsync(); // dataPeople is a tracked entity and will be saved, not people which is acting as a viewmodel.
return RedirectToAction(nameof(Index));
}
Using Update will generate an update statement where all fields on the entity are overwritten. You may decide to pass an incomplete entity to the view, or an incomplete entity back from the view, but EF has no notion of what data is missing because it wasn't provided/changed, vs. what was cleared out so it updates everything. Instead, you should load the entity from the DbContext based on the ID provided (which will error if the ID is not found) then set the properties you want to change on that tracked entity before calling SaveChanges. This ensures that the resulting SQL update statement contains only the columns you want changed.
As a general rule I recommend using view model classes for communicating models between server and client so it is clear what the data being passed around actually is. Passing entities between server and views is an anti-pattern which is prone to performance problems, serialization issues, and both intentional and accidental data corruption.
Additional validations should include making sure the changes are complete/legal, and potentially checking a row version # or last modified date between the passed model and the data loaded from the DB to ensure they match. When the user opened the page they may have gotten version #1 of the record. When they finally submit the form, if the DB returned version #2, it would indicate that someone else modified that row in that time. (Otherwise you are overwriting the changes)
I'm not able to figure out how to run a whole scenario before an other scenario, so that my test are not dependant on eachother.
I have this imaginary scenarios.
Scenario A
Given I have something
When I sumbit some data
I should see it on my webpage
Scenario B
Given SCENARIO A
When I delete the data
I should not see it on my webpage
When I run this scenario case, the software does not recognize Scenario A in scenario B, and ask me to create the step, like this...
You can implement missing steps with the snippets below:
#Given("^Registrere formue og inntekt$")
public void registrere_formue_og_inntekt() throws Throwable {
// Write code here that turns the phrase above into concrete actions
throw new PendingException();
}
You could either:
Use a Background to group all the steps that need to be executed before the different scenarii:
Background:
Given I have something
When I submit some data
Then I should see it on my webpage
Scenario: B
When I delete the data
Then I should not see it on my webpage
Group them as part of a step definition:
#Given("^Scenario A")
public void scenario_A() {
I_have_something();
I_submit_some_data();
I_should_see_it_on_my_page();
}
which you can then use like this:
Given Scenario A
When I delete the data
Then I should not see it on my webpage
Using this technique, you usually observe that some actions are constantly reused, and you may want to factor them out so that they can be reused across different step definitions; at that point, the Page Object pattern comes very handy.
Cucumber scenarios are supposed to be independent. A lot of work is done assuming and ensuring that independence. Trying to go against will be an obstacle course.
Having said that, you could create your custom implementation of the Cucumber JUnit runner. Having this custom implementation, and by looking at the source of the original runner, you can expose / wrap / change the internals to allow what you want. For example with the following runner:
public class MyCucumber extends Cucumber {
private static Runtime runtime;
private static JUnitReporter reporter;
private static List<CucumberFeature> features;
public MyCucumber(Class<?> clazz) throws InitializationError, IOException {
super(clazz);
}
#Override
#SuppressWarnings("static-access")
protected Runtime createRuntime(ResourceLoader resourceLoader,
ClassLoader classLoader, RuntimeOptions runtimeOptions)
throws InitializationError, IOException {
this.runtime = super.createRuntime(resourceLoader, classLoader, runtimeOptions);
this.reporter = new JUnitReporter(runtimeOptions.reporter(classLoader), runtimeOptions.formatter(classLoader), runtimeOptions.isStrict());
this.features = runtimeOptions.cucumberFeatures(resourceLoader);
return this.runtime;
}
public static void runScenario(String name) throws Exception {
new ExecutionUnitRunner(runtime, getScenario(name), reporter).run(new RunNotifier());
}
private static CucumberScenario getScenario(String name) {
for (CucumberFeature feature : features) {
for (CucumberTagStatement element : feature.getFeatureElements()) {
if (! (element instanceof CucumberScenario)) {
continue;
}
CucumberScenario scenario = (CucumberScenario) element;
if (! name.equals(scenario.getGherkinModel().getName())) {
continue;
}
return scenario;
}
}
return null;
}
}
You can setup your test suite with:
#RunWith(MyCucumber.class)
public class MyTest {
}
And create a step definition like:
#Given("^I first run scenario (.*)$")
public void i_first_run_scenario(String name) throws Throwable {
MyCucumber.runScenario(name);
}
It is a fragile customization (can break easily with new versions of cucumber-junit) but it should work.
I tried to solve by myself, but... Looks like I need help from people.
I have Business Silverlight application with WCF RIA and EntityFramework. Access to Database I get via LinqToEntites.
Common loading data from database I making by this:
return DbContext.Customers
This code returns full Customers table from DataBase. But sometimes I do not need to show all data. Easy way is use linq filters in client side by next code:
public LoadInfo()
{
...
var LO1 = PublicDomainContext.Load(PublicDomainContext.GetCustomersQuery());
LO1.Completed += LO1Completed;
...
}
private void LO1Completed(object sender, EventArgs eventArgs)
{
...
DatatViewGrid.ItemsSource = null;
DatatViewGrid.ItemsSource = loadOperation.Entities.Where(c=>c ...filtering...);
//or PublicDomainContext.Customers.Where(c=>c ...filtering...)
...
}
However this way has very and very important flaw: all data passing from server to client side via DomainService may be viewed by applications like Fiddler. So I need to come up with another way.
Task: filter recieving data in server side and return this data.
Way #1: LinqToEntites has a beautiful projection method:
//MSDN Example
var query =
contacts.SelectMany(
contact => orders.Where(order =>
(contact.ContactID == order.Contact.ContactID)
&& order.TotalDue < totalDue)
.Select(order => new
{
ContactID = contact.ContactID,
LastName = contact.LastName,
FirstName = contact.FirstName,
OrderID = order.SalesOrderID,
Total = order.TotalDue
}));
But, unfortunately, DomainServices cannot return undefined types, so this way won't work.
Way #2: I found next solution - make separate DTO classes (DataTransferObject). I just read some samples and made on the server side next class:
[DataContract]
public partial class CustomerDTO
{
[DataMember]
public int ISN { get; set; }
[DataMember]
public string FIO { get; set; }
[DataMember]
public string Listeners { get; set; }
}
And based this class I made a row of methods which return filtered data:
[OperationContract]
public List<CustomerDTO> Customers_Common()
{
return DbContext.Customers....Select(c => new CustomerDTO { ISN = c.ISN, FIO = c.FIO, Listeners = c.Listeners }).ToList();
}
And this works fine, all good...
But, there is strange problem: running application locally does not affect any troubles, but after publishing project on the Web Site, DomainService returns per each method HTTP 500 Error ("Not Found" exception). Of course, I cannot even LogIn into my application. DomainService is dead. If I delete last class and new methods from application and republish - all works fine, but without speacial filtering...
The Question: what I do wrong, why Service is dying with new classes, or tell me another way to solve my trouble. Please.
U P D A T E :
Hey, finally I solved this!
There is an answer: Dynamic query with WCF RIA Services
Your best shot is to find out what is causing the error. For that, override the OnError method on the DomainService like this:
protected override void OnError(DomainServiceErrorInfo errorInfo)
{
/* Log the error info to a file. Don't forget inner exceptions.
*/
base.OnError(errorInfo);
}
This is useful, because only two exceptions will be passed to the client, so if there are a lot of nested inner exceptions, you should still be able to see what actually causes the error.
In addition, you can inspect the error by attaching the debugger to the browser instance you are opening the site with. In VS2010 this is done by doing [Debug] -> [Attach to Process] in the menu-bar.
I'm execute method Datastore.delete(key) form my GWT web application, AsyncCallback had call onSuccess() method .Them i refresh http://localhost:8888/_ah/admin immediately , the Entity i intent to delete still exist. Smilar to, I refresh my GWT web application immediately the item i intent to delete still show on web page.Note the the onSuccess() had been call.
So, how can i know when the Entity already deleted ?
public void deleteALocation(int removedIndex,String symbol ){
if(Window.confirm("Sure ?")){
System.out.println("XXXXXX " +symbol);
loCalservice.deletoALocation(symbol, callback_delete_location);
}
}
public AsyncCallback<String> callback_delete_location = new AsyncCallback<String>() {
public void onFailure(Throwable caught) {
Window.alert(caught.getMessage());
}
public void onSuccess(String result) {
// TODO Auto-generated method stub
int removedIndex = ArryList_Location.indexOf(result);
ArryList_Location.remove(removedIndex);
LocationTable.removeRow(removedIndex + 1);
//Window.alert(result+"!!!");
}
};
SERver :
public String deletoALocation(String name) {
// TODO Auto-generated method stub
Transaction tx = Datastore.beginTransaction();
Key key = Datastore.createKey(Location.class,name);
Datastore.delete(tx,key);
tx.commit();
return name;
}
Sorry i'm not good at english :-)
According to the docs
Returns the Key object (if one model instance is given) or a list of Key objects (if a list of instances is given) that correspond with the stored model instances.
If you need an example of a working delete function, this might help. Line 108
class DeletePost(BaseHandler):
def get(self, post_id):
iden = int(post_id)
post = db.get(db.Key.from_path('Posts', iden))
db.delete(post)
return webapp2.redirect('/')
How do you check the existence of the entity? Via a query?
Queries on HRD are eventually consistent, meaning that if you add/delete/change an entity then immediately query for it you might not see the changes. The reason for this is that when you write (or delete) an entity, GAE asynchronously updates the index and entity in several phases. Since this takes some time it might happen that you don't see the changes immediately.
Linked article discusses ways to mitigate this limitation.
I'm developing a dynamic data app, in which I'm trying perform insert RequestRevision during update of request (logging change of request, somthing like that)
public partial class ProjectDataContext
{
partial void UpdateRequest(Request instance)
{
RequestRevision rv = new RequestRevision(Requests.GetOriginalEntityState(instance));
this.ExecuteDynamicInsert(rv);
this.ExecuteDynamicUpdate(instance);
}
}
this code error "The operation cannot be performed for the entity because it is not being change tracked."
when I added code for change tracking
public partial class ProjectStatusDataContext
{
partial void UpdateRequest(Request instance)
{
bool tracking = ObjectTrackingEnabled;
ObjectTrackingEnabled = true;
RequestRevision rv = new RequestRevision(Requests.GetOriginalEntityState(instance));
//instance.RequestRevisions.Add(rv); --not working
this.ExecuteDynamicInsert(rv);
//this.RequestRevisions.InsertOnSubmit(rv); -- not working
ObjectTrackingEnabled = tracking;
this.ExecuteDynamicUpdate(instance);
}
}
Now I'm getting error "Data context options cannot be modified after results have been returned from a query."
I achieve this using sql triggers. Which fire when an update id performed on the request table.