Getting same Current and Original value of change tracker modified state - entity-framework-6

Below is my override saveChanges Methed which calls SetChanges Method
public override int SaveChanges(bool acceptAllChangesOnSuccess)
{
SetChanges();
OnBeforeSaving();
return base.SaveChanges(acceptAllChangesOnSuccess);
}
Right now, Sometimes code works completely fine but in some scenario It gives same value of both property.OriginalValue and property.CurrentValue for Modification so I am not able find what is the issue in my code
private void SetChanges()
{
Guid SystemLogId = Guid.NewGuid();
var currentDate = DateTime.Now;
var entitiesTracker = ChangeTracker.Entries()
.Where(p => p.State == EntityState.Modified || p.State == EntityState.Added).ToList();
foreach (var entry in entitiesTracker)
{
var pagename = entry.Entity.GetType().Name;
if (pagename != "ExceptionLog")
{
var rowid = 0;
try
{
rowid = int.Parse(entry.OriginalValues["Id"].ToString());
}
catch (Exception)
{ }
SystemLog sysLog = new SystemLog();
List<SystemChangeLog> changeLog = new List<SystemChangeLog>();
foreach (PropertyEntry property in entry.Properties)
{
string propertyName = property.Metadata.Name;
switch (entry.State)
{
case EntityState.Added:
sysLog.Event = "Created";
break;
case EntityState.Modified:
{
sysLog.Event = "Updated";
if (propertyName != "ModifiedDate" && propertyName != "CreatedDate" && propertyName != "ModifiedBy" && propertyName != "CreatedBy" && propertyName != "RowVersion")
{
var original = Convert.ToString(property.OriginalValue);
var current = Convert.ToString(property.CurrentValue);
if (property.IsModified && !original.Equals(current))
{
SystemChangeLog log = new SystemChangeLog()
{
Property = propertyName,
OldValue = original,
NewValue = current,
DateOfChange = currentDate,
rowid = rowid,
SystemLogId = SystemLogId.ToString(),
};
changeLog.Add(log);
}
}
}
break;
}
}
base.Set<SystemChangeLog>().AddRange(changeLog);
if(changeLog.Count() >0 || entry.State == EntityState.Added)
{
sysLog.UserId = UserId;
sysLog.Date = currentDate;
sysLog.Page = pagename;
sysLog.Location = ExceptionHandler(entry, "Location");
sysLog.IPAddress = ExceptionHandler(entry, "IPAddress");
sysLog.MACAddress = ExceptionHandler(entry, "MACAddress");
sysLog.SystemLogId = SystemLogId.ToString();
base.Set<SystemLog>().Add(sysLog);
}
}
}
}
And also Is there any way to make it fast for more than thousand entry

hope below code can help:
public override int SaveChanges(bool acceptAllChangesOnSuccess)
{
setChanges(); // to get new value and old value
var result = base.SaveChanges(acceptAllChangesOnSuccess);
OnAfterSaveChanges();// to get auto added id
return result;
}

Related

EF Core set Original Values in Disconnected Scenario

I am using DBContext.Update(ParentEntity) to update an entity. Then I loop through each of the Entities property.CurrentValue and property.OriginalValue.
The problem I am facing is that CurrentValues and OriginalValues are the same even though one Property has been changed and is different from the DB. I was expecting to get OriginalValues from the Database.
Heres the loop that happens before saving changes.
foreach (var entry in ChangeTracker.Entries())
{
if (entry.Entity is Audit || entry.State == EntityState.Detached || entry.State == EntityState.Unchanged ||entry.Entity is ChangelogUser)
continue;
var auditEntry = new AuditEntry(entry) {TableName = entry.Metadata.Relational().TableName};
auditEntries.Add(auditEntry);
foreach (var property in entry.Properties)
{
if (property.IsTemporary)
{
// value will be generated by the database, get the value after saving
auditEntry.TemporaryProperties.Add(property);
continue;
}
string propertyName = property.Metadata.Name;
if (property.Metadata.IsPrimaryKey())
{
auditEntry.KeyValues[propertyName] = property.CurrentValue;
continue;
}
switch (entry.State)
{
case EntityState.Added:
auditEntry.NewValues[propertyName] = property.CurrentValue;
break;
case EntityState.Deleted:
auditEntry.OldValues[propertyName] = property.OriginalValue;
break;
case EntityState.Modified:
if (property.CurrentValue != null)
{
if (property.OriginalValue != null && property.CurrentValue != null)
{
if (property.IsModified && !property.CurrentValue.Equals(property.OriginalValue))
{
auditEntry.OldValues[propertyName] = property.OriginalValue;
auditEntry.NewValues[propertyName] = property.CurrentValue;
}
}
}
break;
}
}
From this code I AWLAYS get the same Original and Current values. Is there some way to get the Original Values from the DB and set them on the Entity?
Since it is suuuper difficult to get an answer for EFCore Questions hereĀ“s the solution I came up with.
Check out the State.Modified section. I Iterate through each entity and then iterate through each property. In this case, I am using the current and original values to compare them and only add them to my audit table when something has changed.
At the end of the method I remove the Entities that have not changed from my audit table. Simple mimple.
You could use this the var databaseValues = entry.GetDatabaseValues(); To for your custom disconnected scenario needs.
var auditEntries = new List<AuditEntry>();
foreach (var entry in ChangeTracker.Entries())
{
if (entry.Entity is Audit || entry.State == EntityState.Detached || entry.State == EntityState.Unchanged)
continue;
var auditEntry = new AuditEntry(entry) {TableName = entry.Metadata.Relational().TableName};
auditEntries.Add(auditEntry);
var databaseValues = entry.GetDatabaseValues();
foreach (var property in entry.Properties)
{
if (property.IsTemporary)
{
// value will be generated by the database, get the value after saving
auditEntry.TemporaryProperties.Add(property);
continue;
}
string propertyName = property.Metadata.Name;
if (property.Metadata.IsPrimaryKey())
{
auditEntry.KeyValues[propertyName] = property.CurrentValue;
continue;
}
switch (entry.State)
{
case EntityState.Added:
auditEntry.NewValues[propertyName] = property.CurrentValue;
break;
case EntityState.Deleted:
auditEntry.OldValues[propertyName] = property.OriginalValue;
break;
case EntityState.Modified:
if (property.CurrentValue != null)
{
if (databaseValues[propertyName] != null && property.CurrentValue != null)
{
if (property.IsModified && !property.CurrentValue.Equals(databaseValues[propertyName]))
{
auditEntry.OldValues[propertyName] = databaseValues[propertyName];
auditEntry.NewValues[propertyName] = property.CurrentValue;
}
}
}
break;
}
}
if (auditEntry.NewValues.Equals(auditEntry.OldValues) || auditEntry.NewValues.Count == 0 && auditEntry.OldValues.Count == 0)
{
auditEntries.Remove(auditEntry);
}

how to save list of data in memory?

I have an ajax function which is called by the jquery-datatable and ve two responsibility.
To get data from the database.
To serve the search, sort, pagination like functional work.
Now all I need is I just wanna get data once and save it in memory so that when user type something in the search box it performs the search from stored data directly.
Here the code.
public ActionResult AjaxOil(JQueryDataTableParamModel param)
{
//To get data and should be run only once.
IEnumerable<Oil> allOils = _context.Oils.ToList();
//All others function.
IEnumerable<Oil> filteredOils;
if (!string.IsNullOrEmpty(param.sSearch))
{
filteredOils = allOils
.Where(c => c.CommonName.Contains(param.sSearch)
||
c.BotanicalName.Contains(param.sSearch)
||
c.PlantParts.Contains(param.sSearch)
||
c.Distillation.Contains(param.sSearch));
}
else
{
filteredOils = allOils;
}
var sortColumnIndex = Convert.ToInt32(Request["iSortCol_0"]);
Func<Oil, string> orderingFunction = (c => sortColumnIndex == 1 ? c.CommonName :
sortColumnIndex == 2 ? c.BotanicalName :
c.PlantParts);
var distillationFilter = Convert.ToString(Request["sSearch_4"]);
var commonFilter = Convert.ToString(Request["sSearch_1"]);
var botanicalFilter = Convert.ToString(Request["sSearch_2"]);
var plantFilter = Convert.ToString(Request["sSearch_3"]);
if (!string.IsNullOrEmpty(commonFilter))
{
filteredOils = filteredOils.Where(c => c.CommonName.Contains(commonFilter));
}
if (!string.IsNullOrEmpty(botanicalFilter))
{
filteredOils = filteredOils.Where(c => c.BotanicalName.Contains(botanicalFilter));
}
if (!string.IsNullOrEmpty(plantFilter))
{
filteredOils = filteredOils.Where(c => c.PlantParts.Contains(plantFilter));
}
if (!string.IsNullOrEmpty(distillationFilter))
{
filteredOils = filteredOils.Where(c => c.Distillation.Contains(distillationFilter));
}
var sortDirection = Request["sSortDir_0"];
if (sortDirection == "asc")
filteredOils = filteredOils.OrderBy(orderingFunction);
else
filteredOils = filteredOils.OrderByDescending(orderingFunction);
var displayedOils = filteredOils
.Skip(param.iDisplayStart)
.Take(param.iDisplayLength);
var result = from c in displayedOils
select new[] { Convert.ToString(c.OilId), c.CommonName, c.BotanicalName, c.PlantParts, c.Distillation };
return Json(new
{
sEcho = param.sEcho,
iTotalRecords = allOils.Count(),
iTotalDisplayRecords = filteredOils.Count(),
aaData = result
},
JsonRequestBehavior.AllowGet);
On first load save the data in cache/session/static field. On next search check if the cache/session/static field is not null and read from there, not from db, else take again from db..
Example:
private static ObjectCache _cache = new MemoryCache("MemoryCache");
public List<Oils> GetDataFromCache(string keyName)
{
//private static ObjectCache _cache = new MemoryCache("keyName");
var data = _cache.Get(keyName);
if (data != null) return data as List<Oils>;
data = _context.Oils.ToList();
//keep the cache for 2h
_cache.Add(keyName, data, DateTimeOffset.Now.AddHours(2));
return data;
}
(didn't test the code, but that's the logic) or you can use Session if you prefer
Session example:
if(Session["Data_Oils"] != null) { return Session["Data_Oils"] as List<Oils; } else { var temp = _context.Oils.ToList(); Session["Data_Oils"] = temp; return temp; }

What will be the time complexity of reversing the linked list in a different way using below code?

Given a linked List $link1, with elements (a->b->c->d->e->f->g->h->i->j), we need to reverse the linked list provided that the reversing will be done in a manner like -
Reverse 1st element (a)
Reverse next 2 elements (a->c->b)
Reverse next 3 elements (a->c->b->f->e->d)
Reverse next 4 elements (a->c->b->f->e->d->j->i->h->g)
....
....
I have created below code in PHP to solve this problem
Things I need -
I need to calculate the time complexity of reverseLinkedList function below.
Need to know if we can optimize reverseLinkedList function to reduce time complexity.
-
class ListNode
{
public $data;
public $next;
function __construct($data)
{
$this->data = $data;
$this->next = NULL;
}
function read_node()
{
return $this->data;
}
}
class LinkList
{
private $first_node;
private $last_node;
private $count;
function __construct()
{
$this->first_node = NULL;
$this->last_node = NULL;
$this->count = 0;
}
function size()
{
return $this->count;
}
public function read_list()
{
$listData = array();
$current = $this->first_node;
while($current != NULL)
{
echo $current->read_node().' ';
$current = $current->next;
}
}
public function reverse_list()
{
if(($this->first_node != NULL)&&($this->first_node->next != NULL))
{
$current = $this->first_node;
$new = NULL;
while ($current != NULL)
{
$temp = $current->next;
$current->next = $new;
$new = $current;
$current = $temp;
}
$this->first_node = $new;
}
}
public function read_node($position)
{
if($position <= $this->count)
{
$current = $this->first_node;
$pos = 1;
while($pos != $position)
{
if($current->next == NULL)
return null;
else
$current = $current->next;
$pos++;
}
return $current->data;
}
else
return NULL;
}
public function insert($data)
{
$new_node = new ListNode($data);
if($this->first_node != NULL)
{
$this->last_node->next = $new_node;
$new_node->next = NULL;
$this->last_node = &$new_node;
$this->count++;
}
else
{
$new_node->next = $this->first_node;
$this->first_node = &$new_node;
if($this->last_node == NULL)
$this->last_node = &$new_node;
$this->count++;
}
}
}
//Create linked list
$link1 = new LinkList();
//Insert elements
$link1->insert('a');
$link1->insert('b');
$link1->insert('c');
$link1->insert('d');
$link1->insert('e');
$link1->insert('f');
$link1->insert('g');
$link1->insert('h');
$link1->insert('i');
$link1->insert('j');
echo "<b>Input :</b><br>";
$link1->read_list();
//function to reverse linked list in specified manner
function reverseLinkedList(&$link1)
{
$size= $link1->size();
if($size>2)
{
$link2=new LinkList();
$link2->insert($link1->read_node(1));
$elements_covered=1;
//reverse
$rev_size=2;
while($elements_covered<$size)
{
$start=$elements_covered+1;
$temp_link = new LinkList();
$temp_link->insert($link1->read_node($start));
for($i=1;$i<$rev_size;$i++)
{
$temp_link->insert($link1->read_node(++$start));
}
$temp_link->reverse_list();
$temp_size=$temp_link->size();
$link2_size=$link2->size();
for($i=1;$i<=$temp_size;$i++)
{
$link2->insert($temp_link->read_node($i));
++$elements_covered;
++$link2_size;
}
++$rev_size;
}
///reverse
//Flip the linkedlist
$link1=$link2;
}
}
///function to reverse linked list in specified manner
//Reverse current linked list $link1
reverseLinkedList($link1);
echo "<br><br><b>Output :</b><br>";
$link1->read_list();
It's O(n)...just one traversal.
And secondly, here tagging it in language is not necessary.
I have provided a Pseudocode here for your reference:
current => head_ref
prev => NULL;
current => head_ref;
next => null;
while (current != NULL)
{
next = current->next;
current->next = prev;
prev = current;
current = next;
}
*head_ref = prev;

How to add text input field in cocos2d.Android cocos sharp?

I am trying to get CCTextFieldTTF to work in cocos sharp with Xamarin for an android application. But can't get hold of this for the life of me. Could not find any documentation on cocos sharp API either. Does anyone know how to use this class to render a text area in an android application? The reason I am asking is in a xamarin forum I saw someone saying that this does not work in the API yet. Any help would be highly appreciated. Thanks in advance.
I have this working in android
Here is the sample code:
Create a node to track the textfield
CCTextField trackNode;
protected CCTextField TrackNode
{
get { return trackNode; }
set
{
if (value == null)
{
if (trackNode != null)
{
DetachListeners();
trackNode = value;
return;
}
}
if (trackNode != value)
{
DetachListeners();
}
trackNode = value;
AttachListeners();
}
}
//create the actual input textfield
var textField = new CCTextField(string.Empty, "Somefont", 25, CCLabelFormat.SystemFont);
textField.IsColorModifiedByOpacity = false;
textField.Color = new CCColor3B(Theme.TextWhite);
textField.BeginEditing += OnBeginEditing;
textField.EndEditing += OnEndEditing;
textField.Position = new CCPoint (0, 0);
textField.Dimensions = new CCSize(VisibleBoundsWorldspace.Size.Width - (160 * sx), vPadding);
textField.PlaceHolderTextColor = Theme.TextYellow;
textField.PlaceHolderText = Constants.TextHighScoreEnterNamePlaceholder;
textField.AutoEdit = true;
textField.HorizontalAlignment = CCTextAlignment.Center;
textField.VerticalAlignment = CCVerticalTextAlignment.Center;
TrackNode = textField;
TrackNode.Position = pos;
AddChild(textField);
// Register Touch Event
var touchListener = new CCEventListenerTouchOneByOne();
touchListener.OnTouchBegan = OnTouchBegan;
touchListener.OnTouchEnded = OnTouchEnded;
AddEventListener(touchListener);
// The events
bool OnTouchBegan(CCTouch pTouch, CCEvent touchEvent)
{
beginPosition = pTouch.Location;
return true;
}
void OnTouchEnded(CCTouch pTouch, CCEvent touchEvent)
{
if (trackNode == null)
{
return;
}
var endPos = pTouch.Location;
if (trackNode.BoundingBox.ContainsPoint(beginPosition) && trackNode.BoundingBox.ContainsPoint(endPos))
{
OnClickTrackNode(true);
}
else
{
OnClickTrackNode(false);
}
}
public void OnClickTrackNode(bool bClicked)
{
if (bClicked && TrackNode != null)
{
if (!isKeyboardShown)
{
isKeyboardShown = true;
TrackNode.Edit();
}
}
else
{
if (TrackNode != null)
{
TrackNode.EndEdit();
}
}
}
private void OnEndEditing(object sender, ref string text, ref bool canceled)
{
//((CCNode)sender).RunAction(scrollDown);
Console.WriteLine("OnEndEditing text {0}", text);
}
private void OnBeginEditing(object sender, ref string text, ref bool canceled)
{
//((CCNode)sender).RunAction(scrollUp);
Console.WriteLine("OnBeginEditing text {0}", text);
}
void AttachListeners()
{
// Attach our listeners.
var imeImplementation = trackNode.TextFieldIMEImplementation;
imeImplementation.KeyboardDidHide += OnKeyboardDidHide;
imeImplementation.KeyboardDidShow += OnKeyboardDidShow;
imeImplementation.KeyboardWillHide += OnKeyboardWillHide;
imeImplementation.KeyboardWillShow += OnKeyboardWillShow;
imeImplementation.InsertText += InsertText;
}
void DetachListeners()
{
if (TrackNode != null)
{
// Remember to remove our event listeners.
var imeImplementation = TrackNode.TextFieldIMEImplementation;
imeImplementation.KeyboardDidHide -= OnKeyboardDidHide;
imeImplementation.KeyboardDidShow -= OnKeyboardDidShow;
imeImplementation.KeyboardWillHide -= OnKeyboardWillHide;
imeImplementation.KeyboardWillShow -= OnKeyboardWillShow;
imeImplementation.InsertText -= InsertText;
}
}
This is all taken from the link below but needed a bit of additional work to get it working on each platform.
https://github.com/mono/cocos-sharp-samples/tree/master/TextField

LINQ Query using if condition and && Operation

Controller Method for Search
[HttpPost]
public ActionResult Search(string cno, string fname, string lname, string male, string female, string istateid, string icityid, string professionid, string educationid)
{
var db = new clubDataContext();
var query = db.M_Registarions.Where((x=> x.M_ContactNo ==(cno??x.M_ContactNo) && x.M_Fname == (fname ?? x.M_Fname) && x.M_Lname==(lname ?? x.M_Lname) && x.M_Gender == (male??x.M_Gender));
if(istateid != "")
{
int stateid1 = Convert.ToInt32(istateid);
query = query.Where(x=> x.M_StatteId == stateid1);
}
if(icityid != "")
{
int cityid1 = Convert.ToInt32(icityid);
query = query.Where(x=> x.M_CityId == cityid1);
}
if(professionid != "")
{
int professionid1 = Convert.ToInt32(professionid);
query = query.Where(x=> x.P_id == professionid1);
}
if(educationid != "")
{
int educationid1 = Convert.ToInt32(educationid);
query = query.Where(x=> x.P_id == educationid1);
}
if (!query.Any())
{
ViewBag.Count = 0;
}
else
{
var result = query.ToList();
//var search_query = from p in db.M_Registarions where (x => x.M_Fname.Contains(fname ?? x.M_Fname) || x.M_Lname.Contains(lname ?? x.M_Lname)) select p;
ViewBag.SearchResult = result;
ViewBag.Count = 1;
}
return PartialView("SearchResult");
}
Here I am using OR operation in cno, firstname and last name. I want to use &&(And) operation instead of ||(OR). But problem is I have to check for NULL or Space, that I have done in stateid, cityid , professionid and educationid. So how to use if condition in first where? var query = db.M_Registration.Where(if{}) Like this?
Use blocs {} and "return" to put a more complex expression
For example :
db.M_Registration.Where(p =>
{
if{ // my condition... }
return p.Name == name
else
return p.Name == ...
});
You could try this.
[HttpPost]
public ActionResult Search(string cno, string fname, string lname, string male, string female, string istateid, string icityid, string professionid, string educationid)
{
var db = new clubDataContext();
var query = db.M_Registarions.Where((x=> x.M_ContactNo ==(cno??x.M_ContactNo) && x.M_Fname == (fname ?? x.M_Fname) && x.M_Lname==(lname ?? x.M_Lname) && x.M_Gender == (male??x.M_Gender));
if(IntValue(istateid).HasValue)
{
query = query.Where(x=> x.M_StatteId == IntValue(istateid).Value);
}
if(IntValue(icityid).HasValue)
{
query = query.Where(x=> x.M_CityId == IntValue(icityid).Value);
}
if(IntValue(professionid).HasValue)
{
query = query.Where(x=> x.P_id == IntValue(professionid).Value);
}
if(IntValue(educationid).HasValue)
{
query = query.Where(x=> x.P_id == IntValue(educationid).Value);
}
if (!query.Any())
{
ViewBag.Count = 0;
}
else
{
var result = query.ToList();
//var search_query = from p in db.M_Registarions where (x => x.M_Fname.Contains(fname ?? x.M_Fname) || x.M_Lname.Contains(lname ?? x.M_Lname)) select p;
ViewBag.SearchResult = result;
ViewBag.Count = 1;
}
return PartialView("SearchResult");
}
public int? IntValue(string input)
{
int temp;
if (int.TryParse(input, out temp))
{
return temp;
}
return null;
}
I think you could get the result you want and avoid having tons of ifs, by trying the following query:
var query =
db.M_Registarions.Where(
x =>
x.M_ContactNo == (cno ?? x.M_ContactNo) && x.M_Fname == (fname ?? x.M_Fname)
&& x.M_Lname == (lname ?? x.M_Lname) && x.M_Gender == (male ?? x.M_Gender)
&& (string.IsNullOrEmpty(istateid) || x.M_StatteId == Convert.ToInt32(istateid))
&& (string.IsNullOrEmpty(icityid) || x.M_CityId == Convert.ToInt32(icityid))
&& (string.IsNullOrEmpty(professionid) || x.P_id == Convert.ToInt32(professionid))
&& (string.IsNullOrEmpty(educationid) || x.P_id == Convert.ToInt32(educationid)));

Resources