SQLite.net do an insert with Foreign key - sqlite

What is the best solution to save correctly my database :
I want to save this datas in my sqlite databse and export it in CSV, i made a little method, but with this process i can't get the PhotoEnt in my EmailEntity.
PhotoEntity :
public class PhotoEntity : EntityBase
{
[PrimaryKey, AutoIncrement]
public override int Id { get; set; }
public string IdGuid { get; set; }
public string PhotoDate { get; set; }
public string Image { get; set; }
[OneToMany]
public List<EmailEntity> Emails { get; set; }
}
EmailEntity :
public class EmailEntity : EntityBase
{
[PrimaryKey, AutoIncrement]
public override int Id { get; set; }
[ForeignKey(typeof (PhotoEntity))]
public string IdGuid { get; set; }
public string Email { get; set; }
[ManyToOne]
public PhotoEntity PhotoEnt { get; set; }
}
And, when i saved, i do this :
private void DoInsertBddCommand()
{
var guidForId = Guid.NewGuid().ToString();
var dateTime = DateTime.Now.ToString();
var photoEntity = new PhotoEntity
{
IdGuid = guidForId,
Image = _imageName,
PhotoDate = dateTime
};
new PhotoBusiness().Save(photoEntity);
foreach (var item in Emails)
{
var emailEntity = new EmailEntity
{
IdGuid = guidForId,
Email = item,
PhotoEnt = photoEntity
};
new EmailBusiness().Save(emailEntity);
}
}
It's my first time with SQLite.net, any suggestion ?
Thank you

Okay, so here is how I would setup your models:
public class PhotoEntity : EntityBase
{
[PrimaryKey, AutoIncrement]
public override int Id { get; set; }
public string PhotoDate { get; set; }
public string Image { get; set; }
[OneToMany(CascadeOperations = CascadeOperation.All)]
public List<EmailEntity> Emails { get; set; }
}
public class EmailEntity : EntityBase
{
[PrimaryKey, AutoIncrement]
public override int Id { get; set; }
[ForeignKey(typeof (PhotoEntity))]
public int PhotoEntityId { get; set; }
public string Email { get; set; }
[ManyToOne(CascadeOperations = CascadeOperation.All)]
public PhotoEntity PhotoEnt { get; set; }
}
Notice that I define the cascade operations in the relationship attribtues. This is directly from the SQLite-Extensions docs: https://bitbucket.org/twincoders/sqlite-net-extensions#markdown-header-cascade-operations
Now when you save/retrieve objects you need to use the recursive methods:
GetWithChildren
InsertWithChildren
https://bitbucket.org/twincoders/sqlite-net-extensions#markdown-header-cascade-read

Related

List of items relate to two tables one contain foreign key other the primary key and check if item contain primary key is not in the database insert

I have task to get list of items which contain properties related to two tables(Item, PurchaseItemOrder), This list contain the Code property related to Item class this property is not the primary key for business reasons. So I have to search in the database by this Code and if this Item does not exist in the database insert it, And finally return the Id of the Item which is the primary key and get this key as foreign key in another table PurchaseItemOrder, I did some code, and I see this question Check if List of Items exist in database and if not Add it to database, but seems not exactly what I want can I do better?
Here May Code look like:
public class Item :Entity<int> , IFullAudited<User>
{
public string Name_en { get; set; }
public string Name_ar { get; set; }
public string Code { get; set; }
public string Description_en { get; set; }
public string Description_ar { get; set; }
public User CreatorUser { get; set; }
public User LastModifierUser { get; set; }
public long? CreatorUserId { get; set; }
public DateTime CreationTime { get; set; }
public long? LastModifierUserId { get; set; }
public DateTime? LastModificationTime { get; set; }
public User DeleterUser { get; set; }
public long? DeleterUserId { get; set; }
public DateTime? DeletionTime { get; set; }
public bool IsDeleted { get; set; }
}
public class PurchaseOrderItem : Entity<int>, IFullAudited<User>
{
public int POId { get; set; }
public int Qty { get; set; }
public int ItemId { get; set; }
public virtual Item Item { get; set; }
public User CreatorUser { get; set; }
public User LastModifierUser { get; set; }
public long? CreatorUserId { get; set; }
public DateTime CreationTime { get; set; }
public long? LastModifierUserId { get; set; }
public DateTime? LastModificationTime { get; set; }
public User DeleterUser { get; set; }
public long? DeleterUserId { get; set; }
public DateTime? DeletionTime { get; set; }
public bool IsDeleted { get; set; }
public PurchaseOrder PurchaseOrder { get; set; }
}
public class PurchaseOrderItemDto : EntityDto<int>
{
public string PONumber { get; set; }
public List<ItemDto> Items { get; set; }
}
public class ItemDto :EntityDto<int>
{
public string Name_en { get; set; }
public string Name_ar { get; set; }
public string Code { get; set; }
public string Description_en { get; set; }
public string Description_ar { get; set; }
public int Qty { get; set; }
}
private int CheckPO(PurchaseOrderItemDto dto)
{
var poExist = _purchaseOrderRepository.FirstOrDefault(po => po.PONumber == dto.PONumber);
int id;
if (poExist == null)
{
id = _purchaseOrderRepository.InsertAndGetId(new PurchaseOrder
{
PONumber = dto.PONumber,
StatusId = 1
});
}
else
{
id = poExist.Id;
}
return id;
}
private int CheckItem(ItemDto itemDto)
{
var itemExist = _itemRepository.FirstOrDefault(it => it.Code == itemDto.Code);
int id;
if (itemExist == null)
{
id = _itemRepository.InsertAndGetId(new Item
{
Name_en = itemDto.Name_en,
Name_ar = itemDto.Name_en,
Code = itemDto.Code,
Description_en = itemDto.Description_en,
Description_ar = itemDto.Description_ar
});
}
else
{
id = itemExist.Id;
}
return id;
}
public void UploadPurchaseOrderItems(PurchaseOrderItemDto dto)
{
var poId = CheckPO(dto);
foreach (var poItem in dto.Items)
{
int itemId = CheckItem(poItem);
_repository.Insert(new PurchaseOrderItem
{
POId = poId,
Qty = poItem.Qty,
ItemId = itemId
});
}
}

Receiving AutoMapperMappingException

Currently I'm creating a new feature. It looks simple, but I am stuck at a problem with automapping dto to another one.
I have to create a wishlist [adding /deleting items of wishlist].
All works fine, except one thing: while adding an item to the wishlist, I'm get a message like this:
"type": "AutoMapperMappingException",
"message": "Error mapping types..."
However, I can see it got inserted into the database. Also, can delete it too. I understand the problem is linked to Automapper, but I could not figure out how to map correctly.
[HttpPost]
public async Task<IActionResult> Add(WishListItemCreationDto wishListItemDto)
{
var itemAdd = _mapper.Map<WishlistItemDto>(wishListItemDto);
var itemCreated = await _wishListItemService.AddAsync(itemAdd);
return CreatedAtAction(nameof(GetId), new { id = itemCreated.Id }, wishListItemDto);
}
//service
public async Task<WishlistItemDto> AddAsync(WishlistItemDto item)
{
var entity = _mapper.Map<WishlistItem>(item);
var entityDetails = await _productDetailsRepository.GetById(item.ProductDetailId);
entity.ProductDetails = entityDetails;
await _wishListItemRepository.AddAsync(entity);
return _mapper.Map<WishlistItemDto>(entity);
}
DTOs:
public class WishListItemCreationDto
{
[Required]
public string CustomerId { get; set; }
[Required]
public int ProductDetailId { get; set; }
[Min(1)]
[Required]
public int Quantity { get; set; }
}
public class WishlistItemDto
{
public int Id { get; set; }
public string CustomerId { get; set; }
public int ProductDetailId { get; set; }
public ProductDetailsDtoWithPrimaryImage ProductDetails { get; set; }
public int Quantity { get; set; }
}
public class WishlistItem
{
public int Id { get; set; }
public string CustomerId { get; set; }
public Customer Customer { get; set; }
public int ProductDetailsId { get; set; }
public ProductDetails ProductDetails { get; set; }
public int Quantity { get; set; }
}
ProductDetails DTO:
public class ProductDetails
{
public int Id { get; set; }
public int ProductId { get; set; }
public Product Product { get; set; }
public IList<ProductAttributeValue> ProductAttributes { get; set; } = new List<ProductAttributeValue>();
public int Quantity { get; set; }
public string Sku => $"BRD{Id}";
public byte[] RowVersion { get; set; } = new byte[0];
}
public class ProductDetailsDtoWithPrimaryImage
{
public int Id { get; set; }
public int Quantity { get; set; }
public int ProductId { get; set; }
public ProductDisplayEntity Product { get; set; }
public IEnumerable<ProductAttributeWithValueDto> ProductAttributes { get; set; }
public byte[] RowVersion { get; set; }
public string Sku => $"BRD{Id}";
public int? PrimaryImageId { get; set; }
}
AutoMapper:
public WishlistItemProfile()
{
CreateMap<WishlistItem, WishListItemCreationDto>().ReverseMap();
CreateMap<WishlistItemDto, WishListItemCreationDto>().ReverseMap();
CreateMap<WishlistItem, WishlistItemDto>()
.ForMember(wi => wi.ProductDetailId, opt => opt.MapFrom(f => f.ProductDetailsId))
.ForMember(wi => wi.ProductDetails, opt => opt.MapFrom(f => f.ProductDetails))
.ReverseMap();
}
everything is okay, but you missed inner mapping of your classes.
What the error says:
Mapping types:
ProductDetailsDtoWithPrimaryImage -> ProductDetails
SimpleWebApi.Controllers.ProductDetailsDtoWithPrimaryImage -> SimpleWebApi.Controllers.ProductDetails
Add additional mapping in your constructor WishlistItemProfile
CreateMap<ProductDetails, ProductDetailsDtoWithPrimaryImage>().ReverseMap();
And it starts works perfect

generate a list of products of a category

I am developing a shop application and I need to show products of each category. The problem is each product is created from a product template which is stored in a table and each template is related to a category. here is the product model:
namespace fardashahr.Models
{
[Table("Product")]
public class ProductModel
{
public ProductModel()
{
if (Specs == null)
{
Specs = new Dictionary<string, SpecItemsModel>();
}
}
[Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; set; }
[Required]
public int ProductTemplateId { get; set; }
[Required]
public bool IsPublished { get; set; }
[Required]
public bool InStock { get; set; }
[Range(95, 110)]
public float SyncRate { get; set; }
public DateTime? ProductionDate { get; set; }
[Required]
public DateTime RegisterationDate { get; set; }
public string ImageName { get; set; }
public IEnumerable<string> GalleryImages { get; set; }
[NotMapped]
public Dictionary<string, SpecItemsModel> Specs { get; set; }
[ForeignKey("ProductTemplateId")]
public virtual ProductTemplateModel ProductTemplate { get; set; }
[ForeignKey("ManufacturerId")]
public virtual CodingItemModel Manufacturer { get; set; }
[ForeignKey("BrandId")]
public virtual CodingItemModel Brand { get; set; }
[ForeignKey("ModelId")]
public virtual CodingItemModel Model { get; set; }
[ForeignKey("SeriesId")]
public virtual CodingItemModel Series { get; set; }
}
}
and here is the the ProductTemplate:
namespace fardashahr.Models
{
[Table("ProductTemplate")]
public class ProductTemplateModel
{
[Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; set; }
[StringLength(500)]
public string Name { get; set; }
[Required]
public int CategoryId { get; set; }
[StringLength(500)]
public string Description { get; set; }
[ForeignKey("CategoryId")]
public virtual CategoryModel Category{ get; set; }
}
}
and the controller is:
namespace fardashahr.Controllers
{
public class ProductsController : Controller
{
// GET: Products
public ActionResult Index()
{
return RedirectToAction("Index", "Home");
}
public ActionResult Category(string name)
{
//declare a list of products
List<ProductModel> productList;
using(MainModel db = new MainModel())
{
//get category id
CategoryModel category = db.Categories.Where(x => x.CategorytUrl == name).FirstOrDefault();
int catId = category.Id;
//initialize the list
productList = db.Products.Where(x => x. == catId).ToList();
}
}
}
}
finaly, what I want to know is how to initialize a list of products.
In your models, you added virtual keyword which indicates that navigation property will be automatically loaded without the need of LINQ lambda .include() expression.
Hence you can immediately access the navigation property and load the list like this;
productList = db.Products.Where(x => x.ProductTemplate.CategoryId == catId).ToList();
string categoryNameOfFirstProduct = productList.FirstOrDefault().ProductTemplate.Category.Name;
string categoryNameOfFirstProduct = productList.FirstOrDefault().ProductTemplate.Category.CategorytUrl;

Entity Framework Migration created extra column in table

I have following business objects :
public class CreatedCompositeEntity : Entity, IEntity, IModified, ICreated, IIsActive
{
public CreatedCompositeEntity()
{
IsActive = true;
}
[Required, Key]
[Column(Order = 0)]
[DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
public int Id { get; set; }
public DateTime CreatedOn { get; set; }
[Key]
[Column(Order = 1)]
[DatabaseGeneratedAttribute(DatabaseGeneratedOption.None)]
public int CreatedBy { get; set; }
public Nullable<DateTime> ModifiedOn { get; set; }
public Nullable<int> ModifiedBy { get; set; }
public bool IsActive { get; set; }
}
public class HeadCollectionTypeBO : CreatedCompositeEntity
{
public HeadCollectionTypeBO()
{
IsActive = true;
}
public string CollectionType { get; set; }
}
public class HeadBO : CreatedCompositeEntity
{
public HeadBO()
{
IsActive = true;
}
public string HeadName { get; set; }
public int VenueId { get; set; }
public virtual VenueBO Venue { get; set; }
public int CollectionTypeId { get; set; }
public virtual HeadCollectionTypeBO CollectionType { get; set; }
}
After migration is executed, there is extra column has been added in (m_head)HeadBO as CollectionType_Id and CollectionType_CreatedBy. I am very new in Entity Framework. Kindly suggest me solution.

Automapper configuration for object

I have these classes
public class NamedEntityViewModel
{
public string Name { get; set; }
}
public class NamedEntityListViewModel
{
public List<NamedEntityViewModel> List { get; set; }
}
public class Album : INamedEntity
{
public int Id { get; set; }
[Required]
public string Name { get; set; }
public virtual ICollection<Song> Songs { get; set; }
[Required]
public int AlbumNumber { get; set; }
}
I have a List<Album> and I want to map that to NamedEntityListViewModel with NamedEntityViewModel.Name mapping to Album.Name. How do I set this up in Automapper?
Try something like that:
First create you mapper:
Mapper.CreateMap<Album, NamedEntityViewModel>();
For the mapping do this:
// yourAlbumList is a List<Album>
var albumListVm = new NamedEntityListViewModel();
albumListVm.List = Mapper.Map<IEnumerable<NamedEntityViewModel>>(yourAlbumList);
This should do the job

Resources