MVC5 - Object reference not set to an instance of an object. while updating a record - model-view-controller

I have done something similar in the past where it updates the table based on an id. Here is the code worked for me in the past but its returning null error.
Object reference not set to an instance of an object. System.NullReferenceException: Object reference not set to an instance of an object.
public ActionResult TestUpdate()
{
int id = 3; // this is the FK which exists on the Transactions table.
var results = db.StoreTransactions.Find(id);
if(results != null)
{
results.TransStatus = "Completed";
db.SaveChanges();
}
}
It appears that results is null but i verified that the record #3 exists. To simply the code below I hard-coded.
I just want to update the results.TransStatus to "Completed".
Can anyone help please. Thank you!
----------------- UPDATE ---------------------
I found out that Find() does not work with foreign keys(FK). I hard-coded PK and its no longer Null.
However, I'm still not able to update the table to completed. How can I update the table or the transStatus field? Is the code correct? Thanks again for your time.

I fixed it. The db.Entry(results).State = EntityState.Modified was missing. I still don't understand how or why the same code worked on my previous project.

Related

Strange Eloquent belongsTo() return null. Foreign key property being displayed but not accessible

Environment : PHP 8.1.4, Laravel 9
Eloquent Model : Market Model, Sequence Model
Sequence Model belongs to Market Model.
// Sequence.php
public function market()
{
return $this->belongsTo(Market::class);
}
Market and Sequence table has each data properly..
Problem is, Sequence model cannot access its market properly. It looks like $this->market() works fine but $this->market returns null.
// Some method in Sequence.php
private function loadCollection(): CandleCollection
{
dd($this->market(), $this->market);
return $this->collection = $this->market->createCandleCollection($this->label, $this->size);
}
When I dump $this->market(), it returns BelongsTo object and $this->market, it returns null.
Also, $this->market()->toSql() returns
select * from `markets` where `markets`.`id` is null
Strange thing is, it works actually fine just yesterday and I didn't change its code....;; I believe unknown side effect can cause this but I never experience those kine of issue. Any insight help...
Sorry.. I just found that there is an empty method getAttribute($key).. and coworker said he made some joke.

Entity being tracked despite AsNoTracking

I have an object, Client, with a navigation property that is a list of Order objects. Whenever I retrieve a Client object, I include the list of Orders, with AsNoTracking().
public new IQueryable<Client> FindByConditionNoTracking(Expression<Func<Client, bool>> expression)
{
return this.ClientContext.Set<Client>().Include(s => s.Orders)
.Where(expression).AsNoTracking();
}
In my UpdateClient repository method, I take in a Client object. I then attempt to retrieve that original client from the database (using Include to get the child Orders), map the Client param to the original, and save to the database. Over here, I do not use AsNoTracking, because I specifically want the changes to be tracked.
public new void Update(Client client)
{
var id = client.ClientId;
var original = this.ClientContext.Clients.Include(s => s.Orders).Where(s => s.ClientId == id)
.FirstOrDefault<Client>();
original = _mapper.Map(client, original);
this.ClientContext.Update(original);
}
The error I am getting is that an instance of Order with the same key value is already being tracked. A few problems with that:
Wherever the Client and the child Orders are retrieved for the purposes of display I use AsNoTracking.
The only place where I retrieve without AsNoTracking is where I get the original within this very method.
The bug isn't with the parent property. If I was improperly retrieving the Client elsewhere, wouldn't I have this error with the Client id itself? But the error seems to be only with the navigation property.
All insight is appreciated!
If anyone else runs into this: Automapper, when mapping collections, apparently recreates the entire collection. I solved the above issue by using Automapper.Collections in my mapping configuration. Thanks to Mat J for the tip!

Breeze - Can't Create Entity when PK is an autogenerated ID

I have used breeze's CreateEntity a few times when table's PK is a user-entered value. And a few times with SQL SERVER when PK is an IDENTITY. This is my first time trying to do it when PK is autogenerated ID (actually a "sequence") in ORACLE. It isn't working.
I do check first to make sure I have fetched the Metadata then create the new, empty entity that will be filled in with values by user.
My code to createEntity (newEntity is a knockout Observable):
function createEntity(newEntity) {
newEntity(manager.createEntity(entityNames.escctransactions, {})); <<<<< this fails
return;
}
The Error:
Cannot attach an object of type (ESCC_TRANSACTIONS:... ) to an EntityManager without first setting its key or setting its entityType 'AutoGeneratedKeyType' property to something other than 'None'
I know I need to set the AutoGeneratedKeyType to "Identity" but not sure how to do it. Tried this when I'm inititalizing the metadata, but still getting same error so it's obviously not working:
var entyType = manager.metadataStore.getEntityType("ESCC_TRANSACTIONS");
entyType.setProperties({ AutoGeneratedKeyType: AutoGeneratedKeyType.Identity });
I've seen something about doing it in a constructor but I've never used a constructor in JavaScript. Also something about changing it in a config?
Using Breeze 1.6, Knockout.js 3.4, .NET 4.5.2 framework
THANKS
Figured it out myself and it's working now. The code to set AutoGeneratedKeyType is as follows:
var entityType = manager.metadataStore.getEntityType("ESCC_TRANSACTIONS");
entityType.autoGeneratedKeyType = "Identity";
Or this works:
var entityType = manager.metadataStore.getEntityType("ESCC_TRANSACTIONS");
entityType.autoGeneratedKeyType = breeze.AutoGeneratedKeyType.Identity;
And in spite of the Breeze documentation for AutoGeneratedKeyType here:
http://breeze.github.io/doc-js/api-docs/classes/AutoGeneratedKeyType.html, it's not a capital "A" in Auto, it's a small "a".

How to use a Database Generated Identity Key in Web Api OData

I've managed to create number of readonly Web Api OData services following the tutorials here: http://www.asp.net/web-api/overview/odata-support-in-aspnet-web-api. I'm therefore employing the ODataConventionModel builder to create the model from a set of entities (incidentally coming from a Telerik ORM). This all seems to work fine and I can happily issue queries, view the metadata and so forth on the service.
I've now tried to turn my attention to the other CRUD operations - firstly Create and have stumbled into a problem! Namely, the Post method fires correctly (CreateEntity) but the entity parameter is null - by doing a check against the ModelState.IsValid, it shows that the problem is a null ID (key) value. This is unsurprising because the database uses a Database Generated Identity for the ID column and therefore the ID would be created when the entity is saved into the database context.
I've therefore tried all sorts of ways of marking the ID column as database generated, but haven't managed to find anything. Strangely, I can't seem to find even one post of someone asking for this - surely I can't be the only one?!
I noted that when looking at the EF modelbuilder (for example here: http://forums.asp.net/t/1848984.aspx/1) there appears to be a means of affecting the model builder with a .HasDatabaseGeneratedOption property, but no similar option exists in the System.Web.Http.OData equivalent.
So the questions therefore are:
Is there a means of altering the model builder (or something else) so that the controller will accept the object and deserialize the entity even with a null key value?
If so, how can I do this?
If not, any suggestions as to other options?
I realise that I could potentially just populate the object with an (in this case) integer value from the client request, but this seems a) semantically wrong and b) won't necessarilly always be possible as a result of the client toolkit that might be used.
All help gratefully received!
Many thanks,
J.
You need to create a viewmodel for insert which does not contain the ID parameter. Use Automapper to map the properties of the incoming insert-model to your data entities.
The problem that you're having is that ID is a required attribute in your data model because it is your PK, except during insert, where it shouldn't be specified.
In my case, my database-generated key is a Guid.
As a work-around, in my TypeScript client code, I submit (via http POST) the object with an empty Guid like this: Note: ErrorId is the key column.
let elmahEntry: ELMAH_Error = {
Application: 'PTUnconvCost',
Host: this.serviceConfig.url,
Message: message,
User: that.userService.currentUserEmail,
AllXml: `<info><![CDATA[\r\n\r\n${JSON.stringify(info || {})}\r\n\r\n]]></info>`,
Sequence: 1,
Source: source,
StatusCode: 0,
TimeUtc: new Date(Date.now()),
Type: '',
ErrorId: '00000000-0000-0000-0000-000000000000'
};
Then, in my WebApi OData controller, I check to see if the key is the empty guid, and if so, I replace it with a new Guid, like this:
// POST: odata/ELMAH_Error
public IHttpActionResult Post(ELMAH_Error eLMAH_Error)
{
if (eLMAH_Error.ErrorId == Guid.Empty)
{
eLMAH_Error.ErrorId = Guid.NewGuid();
}
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
db.ELMAH_Error.Add(eLMAH_Error);
try
{
db.SaveChanges();
}
catch (DbUpdateException)
{
if (ELMAH_ErrorExists(eLMAH_Error.ErrorId))
{
return Conflict();
}
else
{
throw;
}
}
return Created(eLMAH_Error);
}

Why is this throwing a NULL value exception?

For some reason I am getting the following error at the db.SaveChanges(); instruction:
Cannot insert the value NULL into column 'UserId', table 'XXXXXXXXX_Dev.dbo.Portfolios'; column does not allow nulls. INSERT fails.
The statement has been terminated.
Controller code:
[HttpPost]
[Authorize]
public ActionResult Create(Portfolio portfolio)
{
if (ModelState.IsValid)
{
portfolio.UserId = (Guid)Membership.GetUser().ProviderUserKey;
db.AddToPortfolios(portfolio);
db.SaveChanges();
}
return View("MyPortfolios");
}
I have stepped through the debugger and confirmed that UserID is being populated.
Update:
I have tried changing db.AddToPortfolios(portfolio); to db.Portfolios.AddObject(portfolio); but it is still having the same problem.
Portfolios is an ObjectSet, should I use the Attach() method?
I know this exception from only one situation, that is: UserId is not an identity column in your database but in the EF model the corresponding property is flagged as such - which means it is either explicitely attributed with DatabaseGeneratedOption.Identity or implicitely by conventions.
The problem is that in this case EF won't sent the property value to the Db (no matter if it's set or not) because it assumes that the DB will do the work to create a column value. But the Db doesn't, hence the exception.
Just a guess.
Edit:
To solve the problem you must flag UserId with DatabaseGeneratedOption.None.

Resources