Populate seperate table without relationship in EF Core - c#

I need to add a picture and store the picture Id and product Id in a seperate productPicture table. You can't add a picture without an existing product. How to achieve this?
This is my code for adding an entity to database:
controller:
[HttpPost]
[Route("api/v1/catalog/products/pictures")]
[ProducesResponseType((int)HttpStatusCode.Created)]
[ProducesResponseType((int)HttpStatusCode.BadRequest)]
public async Task<IActionResult> UploadPicture([FromForm]PictureViewModel pic)
{
try
{
var result = await _service.Add(pic);
if (result.HasErrors)
{
return BadRequest(result.Errors);
}
return CreatedAtAction(nameof(GetById), result);
}
catch (Exception ex)
{
return BadRequest(ex.ToString());
}
}
service:
public async Task<ServiceResultWithoutBaseEntity<Picture>> Add(PictureViewModel newItem)
{
var result = new ServiceResultWithoutBaseEntity<Picture>();
result.Errors.AddRange(Validate(newItem));
if (result.HasErrors)
return result;
var item = await newItem.MapToEntity(new Picture());
_context.Pictures.Add(item);
await _context.SaveChangesAsync();
result.EntityResult = item;
return result;
}
helper:
public async static Task<Picture> MapToEntity(this PictureViewModel source, Picture entity)
{
if (source == null || entity == null)
return null;
if (source.FileForUpload != null || source.FileForUpload.Length != 0)
{
AzureBlobExtensions abe = new AzureBlobExtensions();
string folderValue = string.Concat(entity.ID.ToString().ToLower(), "/", DateTime.Now.ToString("yyyyMMddHHmmss"), source.FileForUpload.FileName);
var fileUrl = await abe.UploadFile(source.FileForUpload, folderValue, Path.GetExtension(source.FileForUpload.FileName), "Picture");
entity.VirtualPath = fileUrl;
}
else
{
entity.VirtualPath = source.FileUrl;
}
entity.FileName = source.FileName;
entity.SeoFilename = source.SeoFilename;
entity.AltAttribute = source.AltAttribute;
entity.TitleAtrribute = source.TitleAtrribute;
entity.MimeType = source.MimeType;
entity.IsNew = source.IsNew;
return entity;
}
product table
picture table
productPicture table

Related

Can't Update database with Entity Framework Core

I'm learning asp.net WebApi and EFCore (CodeFirst) and as an exercise, I'm building Warehouse Api and my update method doesn't work.
This is my repository code:
public void Update(T toUpdate)
{
if(toUpdate == null) throw new ArgumentNullException("Entity is null");
T tmp = GetById(toUpdate.Id);
tmp = toUpdate;
_context.SaveChanges();
}
and this is my Service code:
public void UpdateEmployee(UpdateEmployeeCommand command)
{
UpdateEmployeeCommandValidator validator = new UpdateEmployeeCommandValidator();
var results = validator.Validate(command);
if (!results.IsValid)
{
throw new CommandValidationException(results.Errors.Select(x => new CommandValidationError
{
ErrorCode = x.ErrorCode,
ErrorMessage = x.ErrorMessage,
PropertyName = x.PropertyName
}));
}
_repository.Update(new Employee()
{
Id = command.Id,
FirstName = command.FirstName,
Address = command.Address,
LastName = command.LastName,
Age = command.Age,
Email = command.Email,
PhoneNumber = command.PhoneNumber
});
}
and this is how I use it in Controller:
public ActionResult UpdateEmployee(int Id, UpdateEmployeeCommand command)
{
if(Id != command.Id)
{
return BadRequest();
}
var employeeModelFromRepo = _repository.GetById(Id);
if(employeeModelFromRepo == null)
{
return NotFound();
}
_employeeService.UpdateEmployee(command);
return NoContent();
}
When I call UpdateEmployee, it runs without any error but it doesn't update my database.
I'm new to this, so this might be an easy fix.
I am using this generic update function:
public virtual T Update(T t) where T : class, IBaseEntity // contains Id as primary key
{
if (t == null)
return null;
var exist = Context.Set<T>().Find(t);
// Or you can try
var exist = Context.Set<T>()
.Where(i=>i.Id=t.Id).FirstOrdDefault();
if (exist == null) return exist;
Context.Entry(exist).CurrentValues.SetValues(t);
Context.SaveChanges();
return exist;
}
Don't you forget to call your service method in the controller end-point? UpdateEmployee()
Commented solution works, i just had to add db.Entry(tmp).CurrentValues.SetValues(toUpdate) to the repository code.

Business logic in ASP.NET Core MVC

This is my first question here so I'm really open for opinions, I searched a lot about ASP.NET Core MVC and still I don't have enough answers if I'm writing code in right way.
In many tutorials on Youtube I saw people create ASP.NET Core MVC applications with CRUD operations but there were just simple without any logic and all code was in controllers.
What if I want add some logic for example checking if my record already exists in the database? Where should I put this?
I have class Patient and I want add patient to database so I got in patient controller this :
public async Task<IActionResult> Create([Bind("PatientId,Name,Surname,Pesel")] Patient patient)
{
if (ModelState.IsValid)
{
String result = facade.Add_patient(patient);
if (result == "Patient added")
{
_context.Add(patient);
await _context.SaveChangesAsync();
return RedirectToAction(nameof(Index));
}
else
{
ViewBag.Message = "Patient exists";
return View();
}
}
}
Facade is my class in model folder where I have this :
public class Facade
{
private Database_controller _context;
public Facade(Database_controller context)
{
_context = context;
}
private List<Patient> patients = new List<Patient>();
public List<Patient> Patients { get => patients; set => patients = value; }
public void updatedata()
{
patients = _context.Patients.ToList();
}
public string Add_patient(Patient patient)
{
Patient Patient = new Patient();
Patient.Name = patient.Name;
Patient.Surname = patient.Surname;
Patient.Pesel = patient.Pesel;
String if_is = addpacjent(Patient);
if (!"Is".Equals(if_is))
{
return "Patient added";
}
else
{
return "Patient exists";
}
}
public String addpacjent(Patient val)
{
bool if_is = patients.Contains(val);
if (if_is == true)
{
return ("Is");
}
else
{
patients.Add(val);
return null;
}
}
}
In Patient class is override method equals for checking
public override bool Equals(Object ob)
{
String Name = Surname;
String Name2 = ((Patient)ob).Surname;
String Pesel1 = Pesel;
String Pesel2 = ((Patient)ob).Pesel;
bool a = Name.Equals(Name2);
if (Pesel2 != "0")
{
bool b = Pesel1.Equals(Pesel2);
bool c = false;
if (a && b == true)
{
c = true;
}
return c;
}
else
return a;
}
Is it the right way? Should I have method _context.Add(patient) in Facade or controller? Where should I check existence in database?
I already have application which I want write in .NET Core in Winforms so I want use as many as possible code from Winforms classes so it's why I started coding like this in ASP.NET Core MVC
The easiest way is to use Any(),this is because Any() will return as soon as it finds a match.
Like my following:
public IActionResult Test()
{
//Simulation data:
var patient = new Patient
{
Name="AA",
SumName="AA-aa",
Pesel="23"
};
//Here you can add your conditions.
if (!_context.Patients.Any(o => o.Name == patient.Name&&o.SumName==patient.SumName&&o.Pesel==patient.Pesel))
{
_context.Add(patient);
_context.SaveChanges();
return RedirectToAction(nameof(Index));
}
else
{
ViewBag.Message = "Patient exists";
return View();
};
}
Below is the demo data in my database:
Sample effect display:

SQlitedatabase unable to update and delete row

I am working with Xamarin forms and I have implemented SQLite database using Sqlite-net-pcl nuget package. The problem is that the database is initially saving a row but is unable to update or delete any row. Here is the code in which I save and delete the database row with a Key.
public Task<int> SaveItemAsync(SQLiteRowData item)
{
if (item.ID != 0)
{
return database.UpdateAsync(item);
}
else
{
return database.InsertAsync(item);
}
}
public Task<int> DeleteItemAsync(SQLiteRowData item)
{
return database.DeleteAsync(item);
}
public Task<int> DeleteItemAsyncWithKey(string key)
{
Task<SQLite.SQLiteRowData> lSQLiteRowTaskData =
App.sqliteConnectionPath.GetItemForKeyAsync(key);
SQLite.SQLiteRowData lSQLiteRowData = lSQLiteRowTaskData.Result;
return database.DeleteAsync(lSQLiteRowData);
}
public async Task<bool> DeleteUserPreferencesAsync()
{
Boolean lReturnValue = false;
try
{
Task<SQLiteRowData> lSQLiteRowDataTask = App.sqliteConnectionPath.GetItemForKeyAsync("UserPreferences"); SQLiteRowData lSQLiteRowData = lSQLiteRowDataTask.Result;
if (lSQLiteRowData != null) {
await DeleteItemAsync(lSQLiteRowData);
lReturnValue = true;
}
}
catch (Exception ex)
{
EMAUtilities.printLogs(ex.Message);
}
return lReturnValue;
}
// Used for saving userpreference
SQLiteRowData lSQLiteRowData = new SQLiteRowData("UserPreferences", lValue);
Task<int> x = SaveItemAsync(lSQLiteRowData);
Can anyone point out the mistake I have done in this, Thanks in advance

Making a method more generic ASP MVC

I have an Index Method in my FileController that can return a file that is stored in the Attachments entity. How can I change the method to work with any entity not just the Attachments?
public class FileController : Controller
{
private MainDatabaseContext db = new MainDatabaseContext();
// GET: File
public ActionResult Index(int id)
{
var fileToRetrieve = db.Attachments.Find(id);
var FileObject= File (fileToRetrieve.AttachmentObject, fileToRetrieve.ContentType);
if (FileObject.FileDownloadName.Length == 0)
{
FileObject.FileDownloadName = fileToRetrieve.Filename;
}
return FileObject;
}
}
This is what I have done as a workaround, but it has a lot of repeated code which I wanted to avoid:
public class FileController : Controller
{
private MainDatabaseContext db = new MainDatabaseContext();
enum EntityName
{
Attachment=1,
WAProgramApplicationId,
HouseholdIncome,
HouseholdMember
}
// GET: File
public ActionResult Index(int id=0,int WAProgramApplicationId=0,int householdIncomeID=0,int householdMemberId=0)
{
if (householdIncomeID!=0)
{
return GetFileObject(householdIncomeID, EntityName.HouseholdIncome);
}
if (id!=0)
{
return GetFileObject(id, EntityName.Attachment);
}
if (WAProgramApplicationId != 0)
{
return GetFileObject(WAProgramApplicationId, EntityName.WAProgramApplicationId);
}
if (householdMemberId!=0)
{
return GetFileObject(householdMemberId, EntityName.HouseholdMember);
}
return null;
}
private ActionResult GetFileObject(int id, EntityName entityName)
{
if (entityName==EntityName.Attachment)
{
var fileToRetrieve = db.Attachments.Find(id);
var FileObject = File(fileToRetrieve.AttachmentObject, fileToRetrieve.ContentType);
if (FileObject.FileDownloadName.Length == 0)
{
FileObject.FileDownloadName = fileToRetrieve.Filename;
}
return FileObject;
}
if (entityName == EntityName.HouseholdIncome)
{
var fileToRetrieve = db.HouseholdIncomes.Find(id);
var FileObject = File(fileToRetrieve.AttachmentObject, fileToRetrieve.ContentType);
if (FileObject.FileDownloadName.Length == 0)
{
FileObject.FileDownloadName = fileToRetrieve.Filename;
}
return FileObject;
}
if (entityName==EntityName.WAProgramApplicationId)
{
var fileToRetrieve = db.WAProgramApplications.Find(id);
var FileObject = File(fileToRetrieve.AttachmentObject, fileToRetrieve.ContentType);
if (FileObject.FileDownloadName.Length == 0)
{
FileObject.FileDownloadName = fileToRetrieve.Filename;
}
return FileObject;
}
if (entityName==EntityName.HouseholdMember)
{
var fileToRetrieve = db.HouseholdMembers.Find(id);
var FileObject = File(fileToRetrieve.AttachmentObject, fileToRetrieve.ContentType);
if (FileObject.FileDownloadName.Length == 0)
{
FileObject.FileDownloadName = fileToRetrieve.Filename;
}
return FileObject;
}
return null;
}
}
to make the entity more generic just use the Set method, you can do it like this:
db.Set<YourEntity>().Find(id);
They are some approaches how to implement a generic controller with data.
Check here and here.
If you have a repository that can handle _repository.get<T> and return the right object, you can achieve this.

500 Internal Server Error for Store Method

I am gettin an null reference exception inside the Controller on the line:
return await Store.GetSearchDTO();
The error in the console reads:
POST http://localhost:55471/api/GetSearchDTO 500 (Internal Server Error)
Error: Resolving failed with a reason [object Object], but no resolveFailed provided for segment Search
Any insight on why this may be happening would be great.
Controller
namespace Api.Controllers
{
[Authorize]
[RoutePrefix("api/Search")]
public class Controller : ApiController
{
private Store _store;
public Store Store
{
get
{
return _store ?? Request.GetOwinContext().Get<Store>();
}
private set
{
_store = value;
}
}
public Controller()
{
}
public Controller(Store store)
{
Store = store;
}
[HttpPost]
[Route("GetSearchDTO")]
public async Task<SearchDTO> GetSearchDTO()
{
return await Store.GetSearchDTO();
}
}
}
Store
public async Task<SearchDTO> GetSearchDTO()
{
var toReturn = new SearchDTO();
var assessment = await Db.Definitions.Where(x => x.IsActive == true).ToListAsync();
var Types = await Db.Types.ToListAsync();
int i = 0;
int j = 0;
foreach(var assess in assessment)
{
var courseName = await Db.Courses.Where(x => x.Id == assess.CourseId).FirstOrDefaultAsync();
toReturn.CourseIds[i] = courseName.Id;
toReturn.CourseNames[i] = courseName.Name;
toReturn.Names[i] = assess.Name;
i++;
}
foreach(var type in Types)
{
toReturn.TypeIds[j] = type.Id;
toReturn.Types[j] = type.Name;
}
toReturn.SectionFlag = true;
return toReturn;
}
}
}

Categories