EF adding new record instead of updating record - c#

Below is my code to add new records in db. I am using EF Core.
In my code I am checking first if existing user id data is there or not in db, if there is data then it should update record otherwise it should create.
But my problem is every time it is adding new record instead of updating existing one..any idea on this.
Below is my code :
public async Task<int> Create(UserPreference _object)
{
var userPreferenceDetails = applicationDbContext.UserPreferences.Where(x => x.UserId == _object.UserId).FirstOrDefault();
if(userPreferenceDetails != null)
{
if (_object.Image != null)
{
var webRootPath = hostingEnv.WebRootPath;
var fileName = Path.GetFileName(_object.Image.FileName);
var filePath = Path.Combine(hostingEnv.WebRootPath, "images\\User", fileName);
using (var fileStream = new FileStream(filePath, FileMode.Create))
{
await _object.Image.CopyToAsync(fileStream);
}
userPreferenceDetails.ImagePath = filePath;
//_object.ImagePath = filePath;
}
userPreferenceDetails.Name = _object.Name;
userPreferenceDetails.Location = _object.Location;
userPreferenceDetails.DateOfBirth = _object.DateOfBirth;
userPreferenceDetails.AboutMe = _object.AboutMe;
userPreferenceDetails.MatchPreference = _object.MatchPreference;
userPreferenceDetails.PlayScore = _object.PlayScore;
userPreferenceDetails.LocationPreference = _object.LocationPreference;
var obj = applicationDbContext.UserPreferences.Update(_object);
return applicationDbContext.SaveChanges();
} else
{
if (_object.Image != null)
{
var webRootPath = hostingEnv.WebRootPath;
var fileName = Path.GetFileName(_object.Image.FileName);
var filePath = Path.Combine(hostingEnv.WebRootPath, "images\\User", fileName);
using (var fileStream = new FileStream(filePath, FileMode.Create))
{
await _object.Image.CopyToAsync(fileStream);
}
_object.ImagePath = filePath;
}
var obj = await applicationDbContext.UserPreferences.AddAsync(_object);
return applicationDbContext.SaveChanges();
}
}

try this
if(_object.UserId > 0)
{
var userPreferenceDetails = applicationDbContext.UserPreferences.Where(x =>
x.UserId == _object.UserId).FirstOrDefault();
if(userPreferenceDetails == null) return 0;
if (_object.Image != null)
{
....your code
}
userPreferenceDetails.Name = _object.Name;
userPreferenceDetails.Location = _object.Location;
userPreferenceDetails.DateOfBirth = _object.DateOfBirth;
userPreferenceDetails.AboutMe = _object.AboutMe;
userPreferenceDetails.MatchPreference = _object.MatchPreference;
userPreferenceDetails.PlayScore = _object.PlayScore;
userPreferenceDetails.LocationPreference = _object.LocationPreference;
}
else
{
if (_object.Image != null)
{
...your code
}
applicationDbContext.UserPreferences.Add(_object);
}
var result= await applicationDbContext.SaveChangesAsync();
return result;
}

Related

OpenXml how to split a word document into pages

I want to split a Word document into separate pages and save them to files like Page_1.docx; Page_2.docx ......
At first I tried to do this:
using (var sourceWordDoc = WordprocessingDocument.Open(
wordFilePath
, false))
{
var sourceElements = sourceWordDoc.MainDocumentPart.Document.Body.Elements();
var pageElements = new List<DocumentFormat.OpenXml.OpenXmlElement>();
var pageIndex = 1;
foreach (var sourceElement in sourceElements)
{
var run = sourceElement.GetFirstChild<Run>();
if (run != null)
{
var lastRenderedPageBreak = run.GetFirstChild<LastRenderedPageBreak>();
var pageBreak = run.GetFirstChild<Break>();
if (lastRenderedPageBreak != null || pageBreak != null)
{
//Create and save page
using (var destinationWordDoc = WordprocessingDocument.Create(
$"Page_{pageIndex}.docx",
DocumentFormat.OpenXml.WordprocessingDocumentType.Document))
{
var destinationPart = destinationWordDoc.AddMainDocumentPart();
destinationPart.Document = new Document();
var destinationBody = destinationPart.Document.AppendChild(new Body());
foreach (var pageElement in pageElements)
{
destinationBody.Append(pageElement.CloneNode(true));
}
destinationPart.Document.Save();
}
pageElements.Clear();
pageIndex++;
}
}
pageElements.Add(sourceElement);
}
}
But in this variand, Header is not copied.
Then I wrote the following code to copy the Header (for test):
using (var sourceWordDoc = WordprocessingDocument.Open(
wordFilePath
, false))
{
var sourceHeaderPart = sourceWordDoc.MainDocumentPart.HeaderParts.FirstOrDefault();
var sourceDocument = sourceWordDoc.MainDocumentPart.Document;
using (var destinationWordDoc = WordprocessingDocument.Create(
somePath
, WordprocessingDocumentType.Document))
{
var destinationMainDocumentPart = destinationWordDoc.AddMainDocumentPart();
destinationMainDocumentPart.Document = new DocumentFormat.OpenXml.Wordprocessing.Document();
var destinationBody = destinationMainDocumentPart.Document.AppendChild(new DocumentFormat.OpenXml.Wordprocessing.Body());
var rId = string.Empty;
if (sourceHeaderPart != null)
{
var destinationHeaderPart = destinationMainDocumentPart.AddNewPart<HeaderPart>();
rId = destinationMainDocumentPart.GetIdOfPart(destinationHeaderPart);
destinationHeaderPart.FeedData(sourceHeaderPart.GetStream());
}
var sourceElements = sourceDocument.Body.Elements();
foreach (var sourceElement in sourceElements)
{
if (sourceElement.GetType() == typeof(DocumentFormat.OpenXml.Wordprocessing.SectionProperties))
{
var sourceSectionsElements = sourceElement.Elements();
foreach (var sourceSectionsElement in sourceSectionsElements)
{
if (sourceSectionsElement.GetType() == typeof(DocumentFormat.OpenXml.Wordprocessing.HeaderReference))
{
var sourceHeaderReference = (DocumentFormat.OpenXml.Wordprocessing.HeaderReference)sourceSectionsElement;
sourceHeaderReference.Id = rId;
break;
}
}
}
destinationBody.Append(sourceElement.CloneNode(true));
}
}
}
But now I have a new problem, images from the header are not transferred.
Are there any options to break the document into separate pages and at the same time preserve the entire content of the page?

HangFire running each job separately

I am using HangFire to run the job. I have a method that retrieve data from more than 50 sql servers.
I want to use HangFire to run each location separately by LocationID, and if 1 location fails I want that job get running again for that location after x minutes.
Also I want to see the log of the job on the HangFire Dashboard.
My job method :
public void SyncCompInfo()
{
List<Location> locations;
using (var db = new CompInfoDemoEntities())
{
locations = db.Locations.Where(x => x.IsActive).ToList();
}
foreach (var location in locations)
{
try
{
using (var _db = new CompInfoDemoEntities())
{
_log.Info("Getting CompoInfo data from location: " + location.StoreName);
_syncLogService.Add("Getting CompoInfo data from location: " + location.StoreName);
var responses = new List<CompInfoResponse>();
var compInfos = _db.IMS_CompInfo.Where(x => x.LocationId == location.Id).ToList();
using (var cnn = new SqlConnection(location.ConnectionString))
{
var sql = "select * from IMS_CompInfo;";
var sqlCmd = new SqlCommand(sql, cnn);
cnn.Open();
using (SqlDataReader rdr = sqlCmd.ExecuteReader())
{
while (rdr.Read())
{
var item = new CompInfoResponse();
item.Id = int.Parse(rdr["Id"].ToString());
item.ClientID = rdr["ClientID"].ToString();
item.LicenceID = rdr["LicenceID"].ToString();
item.POSCode = rdr["POSCode"].ToString();
item.logiPOS_Version = rdr["logiPOS_Version"].ToString();
if (rdr["LastLoginDate"] != null)
{
item.LastLoginDate = DateTime.Parse(rdr["LastLoginDate"].ToString());
}
item.ComputerName = rdr["ComputerName"].ToString();
if (rdr["BootTime"] != null)
{
item.BootTime = DateTime.Parse(rdr["BootTime"].ToString());
}
item.Domain = rdr["Domain"].ToString();
item.Manufacturer = rdr["Manufacturer"].ToString();
item.Model = rdr["Model"].ToString();
item.Memory = rdr["Memory"].ToString();
item.OS = rdr["OS"].ToString();
item.Build = rdr["Build"].ToString();
item.CPU = rdr["CPU"].ToString();
item.ProcArchitecture = rdr["ProcArchitecture"].ToString();
item.IP1 = rdr["IP1"].ToString();
item.MAC1 = rdr["MAC1"].ToString();
if (rdr["LastModifiedDate"] != null)
{
item.LastModifiedDate = DateTime.Parse(rdr["LastModifiedDate"].ToString());
}
if (rdr["Tag"] != null)
{
item.Tag = int.Parse(rdr["Tag"].ToString());
}
item.Application = rdr["Application"].ToString();
responses.Add(item);
}
}
}
What you seem to need is something like this, with a method you call upon startup, which loops other the locations and enqueues a job for each location.
I over simplified the thing (for example making the methods static),
but I guess most of the idea is there.
Have a look at Hangfire recurring tasks I guess it may be better suited to your needs than tasks fired upon application startups.
public void CalledUponStartup()
{
List<Location> locations;
using (var db = new CompInfoDemoEntities())
{
locations = db.Locations.Where(x => x.IsActive).ToList();
}
foreach (var location in locations)
{
BackgroundJob.Enqueue(() => SyncCompInfo(location.Id));
}
}
public static void SyncCompInfo(int locationId)
{
try
{
using (var _db = new CompInfoDemoEntities())
{
var location = db.Locations.FirstOrDefault(x => x.Id == locationId);
_log.Info("Getting CompoInfo data from location: " + location.StoreName);
_syncLogService.Add("Getting CompoInfo data from location: " + location.StoreName);
var responses = new List<CompInfoResponse>();
var compInfos = _db.IMS_CompInfo.Where(x => x.LocationId == location.Id).ToList();
using (var cnn = new SqlConnection(location.ConnectionString))
{
var sql = "select * from IMS_CompInfo;";
var sqlCmd = new SqlCommand(sql, cnn);
cnn.Open();
using (SqlDataReader rdr = sqlCmd.ExecuteReader())
{
while (rdr.Read())
{
var item = new CompInfoResponse();
item.Id = int.Parse(rdr["Id"].ToString());
item.ClientID = rdr["ClientID"].ToString();
item.LicenceID = rdr["LicenceID"].ToString();
item.POSCode = rdr["POSCode"].ToString();
item.logiPOS_Version = rdr["logiPOS_Version"].ToString();
if (rdr["LastLoginDate"] != null)
{
item.LastLoginDate = DateTime.Parse(rdr["LastLoginDate"].ToString());
}
item.ComputerName = rdr["ComputerName"].ToString();
if (rdr["BootTime"] != null)
{
item.BootTime = DateTime.Parse(rdr["BootTime"].ToString());
}
item.Domain = rdr["Domain"].ToString();
item.Manufacturer = rdr["Manufacturer"].ToString();
item.Model = rdr["Model"].ToString();
item.Memory = rdr["Memory"].ToString();
item.OS = rdr["OS"].ToString();
item.Build = rdr["Build"].ToString();
item.CPU = rdr["CPU"].ToString();
item.ProcArchitecture = rdr["ProcArchitecture"].ToString();
item.IP1 = rdr["IP1"].ToString();
item.MAC1 = rdr["MAC1"].ToString();
if (rdr["LastModifiedDate"] != null)
{
item.LastModifiedDate = DateTime.Parse(rdr["LastModifiedDate"].ToString());
}
if (rdr["Tag"] != null)
{
item.Tag = int.Parse(rdr["Tag"].ToString());
}
item.Application = rdr["Application"].ToString();
responses.Add(item);
}
}

How to modify web api to return message not matched when compare excel function return false?

I work on asp.net core 2.2 i face issue I can't
modify web api to display message "Not Matched Compare"
when compare excel function return false (areIdentical == false) .
web api below return physical file as zip file
in case of compare excel return true
but I need when compare excel function return false
to display message "Not matched compare"
so How to do it please ?
what i try
public IActionResult ExportNormalizedRelation()
{
var InputfilePath = System.IO.Path.Combine(GetFilesDownload, "DeliveryGenerationNormalTest_Input.xlsx");
using (var stream = new FileStream(dbPath, FileMode.Create))
{
Request.Form.Files[0].CopyTo(stream);
stream.Flush();
stream.Close();
}
bool areIdentical = ex.CompareExcel(dbPath, InputfilePath, out rowCount, out error);
if (areIdentical == true)
{
pathToCreate = Path.Combine(myValue2,Month,"file" + DateTime.Now.Ticks.ToString());
Directory.CreateDirectory(pathToCreate);
List<inputexcelnormaltest> inputexcellist = new List<inputexcelnormaltest>();
inputexcellist = ex.ImportNormalTest(dbPath);
List<string> tabs = new List<string>();
var outputTemplatePath = System.IO.Path.Combine(GetFilesDownload, "DeliveryGeneration_Output.xlsx");
List<inputexcelnormaltest> inputmodulelist = new List<inputexcelnormaltest>();
foreach (var m in tabs)
{
inputmodulelist.Clear();
inputmodulelist = inputexcellist.Where(x => (x.TabName == m && x.FileName == f)).ToList();
var dtimport = DatatableConversion.ToDataTable(inputmodulelist);
DataTable dtexport = new DataTable();
dtexport = _deliveryService.LoadExcelToDataTableZipData(_connectionString, dtimport);
ex.Export(dtexport, m, exportPath);
}
}
string zipPath = Path.Combine(myValue2,Month,"result" + DateTime.Now.Ticks.ToString() + ".zip");
ZipFile.CreateFromDirectory(pathToCreate, zipPath);
return PhysicalFile(zipPath, "application/zip", Path.GetFileName(zipPath));
}
expected result
if (areIdentical == false)
return "Not Matched Compare"
so How to do that ?
i solved my issue
i only add return return new JsonResult("Not Matched Excel");
public IActionResult ExportNormalizedRelation()
{
var InputfilePath = System.IO.Path.Combine(GetFilesDownload, "DeliveryGenerationNormalTest_Input.xlsx");
using (var stream = new FileStream(dbPath, FileMode.Create))
{
Request.Form.Files[0].CopyTo(stream);
stream.Flush();
stream.Close();
}
bool areIdentical = ex.CompareExcel(dbPath, InputfilePath, out rowCount, out error);
if (areIdentical == false)
{
return new JsonResult("Not Matched Excel");
}
else
{
pathToCreate = Path.Combine(myValue2,Month,"file" + DateTime.Now.Ticks.ToString());
Directory.CreateDirectory(pathToCreate);
List<inputexcelnormaltest> inputexcellist = new List<inputexcelnormaltest>();
inputexcellist = ex.ImportNormalTest(dbPath);
List<string> tabs = new List<string>();
var outputTemplatePath = System.IO.Path.Combine(GetFilesDownload, "DeliveryGeneration_Output.xlsx");
List<inputexcelnormaltest> inputmodulelist = new List<inputexcelnormaltest>();
foreach (var m in tabs)
{
inputmodulelist.Clear();
inputmodulelist = inputexcellist.Where(x => (x.TabName == m && x.FileName == f)).ToList();
var dtimport = DatatableConversion.ToDataTable(inputmodulelist);
DataTable dtexport = new DataTable();
dtexport = _deliveryService.LoadExcelToDataTableZipData(_connectionString, dtimport);
ex.Export(dtexport, m, exportPath);
}
}
string zipPath = Path.Combine(myValue2,Month,"result" + DateTime.Now.Ticks.ToString() + ".zip");
ZipFile.CreateFromDirectory(pathToCreate, zipPath);
return PhysicalFile(zipPath, "application/zip", Path.GetFileName(zipPath));
}

How do I refactor the code which contains foreach loop

I need to refactor the below code so that the deleted_at logic will be outside of the foreach (var app in data) loop. I tried to create the list guids and then add guids to it but its not working because model.resources is inside the loop and it is still deleting all the apps.
I need deleted_at logic outside because I'm trying to delete all apps which are in the database but are not in new data that I'm receiving from API.
If you have a better approach on my code I would love to see that, Thank you.
public async Task GetBuilds()
{
var data = new List<GetBuildTempClass>();
var guids = new List<GetBuildTempClass>();
using (var scope = _scopeFactory.CreateScope())
{
var _DBcontext = scope.ServiceProvider.GetRequiredService<PCFStatusContexts>();
foreach (var app in data)
{
var request = new HttpRequestMessage(HttpMethod.Get,
"apps/" + app.AppGuid + "/builds?per_page=200&order_by=updated_at");
var response = await _client_SB.SendAsync(request);
var json = await response.Content.ReadAsStringAsync();
BuildsClass.BuildsRootObject model =
JsonConvert.DeserializeObject<BuildsClass.BuildsRootObject>(json);
foreach (var item in model.resources)
{
var x = _DBcontext.Builds.FirstOrDefault(o =>
o.Guid == Guid.Parse(item.guid));
if (x == null)
{
_DBcontext.Builds.Add(new Builds
{
Guid = Guid.Parse(item.guid),
State = item.state,
CreatedAt = item.created_at,
UpdatedAt = item.updated_at,
Error = item.error,
CreatedByGuid = Guid.Parse(item.created_by.guid),
CreatedByName = item.created_by.name,
CreatedByEmail = item.created_by.email,
AppGuid = app.AppGuid,
AppName = app.AppName,
Foundation = 2,
Timestamp = DateTime.Now
});
}
else if (x.UpdatedAt != item.updated_at)
{
x.State = item.state;
x.UpdatedAt = item.updated_at;
x.Timestamp = DateTime.Now;
}
var sqlresult = new GetBuildTempClass
{
AppGuid = Guid.Parse(item.guid)
};
guids.Add(sqlresult);
}
//var guids = model.resources.Select(r => Guid.Parse(r.guid));
var builds = _DBcontext.Builds.Where(o =>
guids.Contains(o.Guid) == false &&
o.Foundation == 2 && o.DeletedAt == null);
foreach (var build_item in builds)
{
build_item.DeletedAt = DateTime.Now;
}
}
await _DBcontext.SaveChangesAsync();
}
}
I got it working I added var guids = new List < Guid > (); list to store data,
added guids.Add(Guid.Parse(item.guid)); to populate the list and finally wrote var builds = _DBcontext.Builds.Where(o = >guids.Contains(o.Guid) == false && o.Foundation == 2 && o.DeletedAt == null); outside the loop.
If anyone has a better suggestion please add a new answer.
public async Task GetBuilds() {
var data = new List < GetBuildTempClass > ();
var guids = new List < Guid > ();
using(var scope = _scopeFactory.CreateScope()) {
var _DBcontext = scope.ServiceProvider.GetRequiredService < PCFStatusContexts > ();
foreach(var app in data) {
var request = new HttpRequestMessage(HttpMethod.Get, "apps/" + app.AppGuid + "/builds?per_page=200&order_by=updated_at");
var response = await _client_SB.SendAsync(request);
var json = await response.Content.ReadAsStringAsync();
BuildsClass.BuildsRootObject model = JsonConvert.DeserializeObject < BuildsClass.BuildsRootObject > (json);
foreach(var item in model.resources) {
var x = _DBcontext.Builds.FirstOrDefault(o = >o.Guid == Guid.Parse(item.guid));
if (x == null) {
_DBcontext.Builds.Add(new Builds {
Guid = Guid.Parse(item.guid),
State = item.state,
CreatedAt = item.created_at,
UpdatedAt = item.updated_at,
Error = item.error,
CreatedByGuid = Guid.Parse(item.created_by.guid),
CreatedByName = item.created_by.name,
CreatedByEmail = item.created_by.email,
AppGuid = app.AppGuid,
AppName = app.AppName,
Foundation = 2,
Timestamp = DateTime.Now
});
}
else if (x.UpdatedAt != item.updated_at) {
x.State = item.state;
x.UpdatedAt = item.updated_at;
x.Timestamp = DateTime.Now;
}
guids.Add(Guid.Parse(item.guid));
}
}
var builds = _DBcontext.Builds.Where(o = >guids.Contains(o.Guid) == false && o.Foundation == 2 && o.DeletedAt == null);
foreach(var build_item in builds) {
build_item.DeletedAt = DateTime.Now;
}
await _DBcontext.SaveChangesAsync();
}
}

How to fetch the data from SqLite database

I have created database in SqLite in my windows app, now I want to fetch the data from my database. This is the code how I inserted the data in databse.
var dbpath = Path.Combine(Windows.Storage.ApplicationData.Current.LocalFolder.Path, "scrapbook.sqlite");
using (var db = new SQLite.SQLiteConnection(dbpath))
{
// Create the tables if they don't exist
var bg = listAlbumContainer[0] as AlbumContainer;
var albumbg = bg.BackgroundImageName;
var sk = listAlbumContainer[0].listAlbumContainer;
var _audio = listAlbumContainer[0].listAlbumContainer5;
var _video = listAlbumContainer[0].listAlbumContainer3;
var wa = listAlbumContainer[0].listAlbumContainer4;
var ci = listAlbumContainer[0].listAlbumContainer2;
var gi = listAlbumContainer[0].listAlbumContainer1;
string snodesticker = Serializeanddeserializwhelper.Serialize(sk);
string nodegi = Serializeanddeserializwhelper.Serialize(gi);
string nodeci = Serializeanddeserializwhelper.Serialize(ci);
string nodewa = Serializeanddeserializwhelper.Serialize(wa);
string nodevideo = Serializeanddeserializwhelper.Serialize(_video);
string nodeaudio = Serializeanddeserializwhelper.Serialize(_audio);
var TittledataInsertCheck = db.Table<Title>().Where(x => x.ALBUM_TITLE.Contains(nametxt.Text)).FirstOrDefault();
if (TittledataInsertCheck == null)
{
db.Insert(new Title()
{
ALBUM_TITLE = nametxt.Text
});
var TittledataInsert = db.Table<Title>().Where(x => x.ALBUM_TITLE.Contains(nametxt.Text)).FirstOrDefault();
if (TittledataInsert != null)
{
db.Insert(new PAGE()
{
PAGE_BACKGROUND = albumbg,
TITLE_ID = TittledataInsert.ID
});
}
}
else
{
await new MessageDialog("Tittle Already Found Please change tittle").ShowAsync();
return;
}
var PagedataInsert = db.Table<PAGE>().Where(x => x.PAGE_BACKGROUND.Contains(albumbg)).FirstOrDefault();
if (PagedataInsert != null)
{
db.Insert(new CONTENT
{
PAGE_ID = PagedataInsert.ID,
STICKERS = snodesticker,
AUDIO = nodeaudio,
VIDEO = nodevideo,
GALLERY_IMAGES = nodegi,
CAMERA_IMAGES = nodeci,
WOARD_ART = nodewa
});
}
db.Commit();
db.Dispose();
db.Close();
var line = new MessageDialog("Records Inserted");
await line.ShowAsync();
}
Is this the right way to insert the data?
I have a canvas on which I set the background image. And on this background some images, video and audio.

Categories