0
\$\begingroup\$

i want to generate value using current date and ID of inserted entity
problem is that ID value not generated until insert object to database, so i use this code for generate value:

public ActionResult Create([Bind(Include = "ID,TrackingCode,FirstName,LastName,ProductName,CurrentStats,FailureReason,ReceiveDateTime,DeliveryDateTime,Price,Description,SerialNumber,ExtraItems,PhoneNumber")] Tracking tracking)
    {
        if (ModelState.IsValid)
        {
            db.Trackings.Add(tracking);
            db.SaveChanges();
            Tracking _tracking = db.Trackings.Find(tracking.ID);
            db.Entry(_tracking).State = EntityState.Modified;
            _tracking.TrackingCode = Convert.ToInt32(DateTime.Now.ToString("yyyyMMdd") + tracking.ID.ToString());
            db.SaveChanges();
            return RedirectToAction("Index");
        }

        return View(tracking);
    }  

code work fine and do job that i want but i think this is not standard way is there any better approach to improve this code?

\$\endgroup\$
  • 1
    \$\begingroup\$ Off-topic: this is not a review task but a question how to solve a programming problem. Your current code doesn't work as intended. \$\endgroup\$ – Gert Arnold Oct 16 '17 at 7:31
  • 1
    \$\begingroup\$ @GertArnold code work fine and do what i want , but i think this is not standard way \$\endgroup\$ – AminM Oct 16 '17 at 7:40
  • 1
    \$\begingroup\$ problem is that ID value not generated until insert object to database So your code doesn't work the way you want it to work. You want it to do it all in one transaction. Also, it's not clear what ToPeString does. \$\endgroup\$ – Gert Arnold Oct 16 '17 at 7:46
  • \$\begingroup\$ @GertArnold ToPeString is just extension Method \$\endgroup\$ – AminM Oct 16 '17 at 8:02
  • 1
    \$\begingroup\$ @Vogel612 That's not my point. My point is: I would never say that the code works fine because if the second SaveChanges fails the database content is inconsistent. For me, this is a Stack-Overflow question because the code must be fixed. \$\endgroup\$ – Gert Arnold Oct 16 '17 at 10:25
2
\$\begingroup\$

I would suggest you change your database design.

Option 1)

Have SQL Server set a column to the current date/time when you insert a row See https://stackoverflow.com/q/6594589 for how to do it. Then have that column mapped on your Tracking entity but mark the property as [DatabaseGenerated(DatabaseGeneratedOption.Computed)]

Assuming you call the field AddDate

[DatabaseGenerated(DatabaseGeneratedOption.Computed)]
public datetime AddDate {get;set;}

Now you can create your get only TrackingCode property in code and use the [NotMapped] on it and define it as

[NotMapped]
public int TrackingCode 
{
     get { return Convert.ToInt32(AddDate.ToString("yyyyMMdd") + tracking;
}

Option 2:

Create an after insert tigger and have SQL Server update the TrackingCode. Again I would mark the property as DatabaseGenerated

In a nut shell it's better to offload this to the SQL Server

| improve this answer | |
\$\endgroup\$
  • \$\begingroup\$ why add DatabaseGeneratedOption.Computed to datetime?? i have problem with ID value \$\endgroup\$ – AminM Oct 17 '17 at 13:42
  • \$\begingroup\$ That tells Entity framework to retrieve the field but don't update the field as the database will be the one to generate the value and not the entity. \$\endgroup\$ – CharlesNRice Oct 17 '17 at 13:43
  • \$\begingroup\$ why Propery dont have setter and you just put getter only? \$\endgroup\$ – AminM Oct 17 '17 at 14:04
  • \$\begingroup\$ IF you go with option 1 you have sql update a new column. I called it add date. Then you just make a calculated property to use in your code. If you actually want the value to be in a column in SQL then I suggest you do option 2 \$\endgroup\$ – CharlesNRice Oct 17 '17 at 14:06

Not the answer you're looking for? Browse other questions tagged or ask your own question.