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\$
9
  • 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\$ Commented Oct 16, 2017 at 7:31
  • 1
    \$\begingroup\$ @GertArnold code work fine and do what i want , but i think this is not standard way \$\endgroup\$
    – AminM
    Commented Oct 16, 2017 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\$ Commented Oct 16, 2017 at 7:46
  • \$\begingroup\$ @GertArnold ToPeString is just extension Method \$\endgroup\$
    – AminM
    Commented Oct 16, 2017 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\$ Commented Oct 16, 2017 at 10:25

1 Answer 1

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

\$\endgroup\$
4
  • \$\begingroup\$ why add DatabaseGeneratedOption.Computed to datetime?? i have problem with ID value \$\endgroup\$
    – AminM
    Commented Oct 17, 2017 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\$ Commented Oct 17, 2017 at 13:43
  • \$\begingroup\$ why Propery dont have setter and you just put getter only? \$\endgroup\$
    – AminM
    Commented Oct 17, 2017 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\$ Commented Oct 17, 2017 at 14:06

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