Realm primary key not getting stored - database

Data Model:
public class Product : RealmObject
{
[PrimaryKey,JsonProperty(PropertyName = "productId")]
public int ProductId { get; set; }
[JsonProperty(PropertyName = "parentId")]
public int ParentId { get; set; }
[JsonProperty(PropertyName = "productType")]
public string ProductType { get; set; }
}
Method used to add product to db:
public void AddSampleProduct(Product product)
{
var _realm = Realm.GetInstance();
using (var transaction = _realm.BeginWrite())
{
var entry = _realm.Add(product);
transaction.Commit();
}
}
Method used to retrieve product:
public Product GetProductById(int id)
{
Product product = null;
var _realm = Realm.GetInstance();
product = _realm.Find<Product>(id);
var p = _realm.Find<Product>(id);
return product;
}
Method to fetch list of products:
public List<Product> GetProductList()
{
List<Product> productList = new List<Product>();
var _realm = Realm.GetInstance();
productList = _realm.All<Product>().ToList();
return productList;
}
Whenever I try to fetch a product using an id it returns null, at the same time if i try to fetch the list am getting all the products but with the primary key property having the value 0 for all the products. Probably the primary key is not getting stored and hence am not able to fetch individual product using id.
Also, in the model class I had tried defining the primary key and Json Property in separate lines like mentioned below.
public class Product : RealmObject
{
[PrimaryKey]
[JsonProperty(PropertyName = "productId")]
public int ProductId { get; set; }
[JsonProperty(PropertyName = "parentId")]
public int ParentId { get; set; }
[JsonProperty(PropertyName = "productType")]
public string ProductType { get; set; }
}

Related

Dapper multi object query One-Many

Not really sure why I'm not getting the child object populated.
My tables:
Product:
[ProductId]
,[Brand]
,[Model]
StoreProduct:
[StoreId]
,[ProductId]
,[StoreProductId]
Class
public class Product
{
public Guid ProductId { get; set; }
public string Brand { get; set; }
public string Model { get; set; }
public virtual List<StoreProduct> StoreProducts { get; set; }
}
public class StoreProduct
{
public int StoreId { get; set; } //Key 0
public Guid ProductId { get; set; } //Key 1
public Store Store { get; set; }
public Product Product { get; set; }
public string StoreProductId { get; set; } //A new Id specific for each store
}
My Dapper Code
string sql = "SELECT * FROM StoreProduct AS A INNER JOIN Product AS B ON A.ProductId = B.ProductId WHERE A.StoreProductId = #StoreProductId and A.StoreId = #StoreId";
var connection = AppDbContext.Database.GetDbConnection();
return connection.Query<StoreProduct, Product, Product>(
sql,
(StoreProduct, Product) => { StoreProduct.ProductId = Product.ProductId; return Product; },
new { StoreProductId = storeProductId, StoreId = StoreID }, splitOn: "ProductId")
.FirstOrDefault();
What the DB returns:
But... StoreProducts List is null.
Use Dapper the way it works.
var listProduct = new Dictionary<string, Product>();
var listStoreProduct = new Dictionary<string, StoreProduct>();
using var connection = _connectionProvider.GetConnection();
var query = "SELECT * FROM StoreProduct AS A INNER JOIN Product AS B ON A.ProductId = B.ProductId WHERE A.StoreProductId = #StoreProductId and A.StoreId = #StoreId";
var result = connection.Query<Product, StoreProduct, Product>(query, (product, storeProduct) =>
{
if (!listProduct.TryGetValue(product.Id, out var entry))
{
entry = product;
listProduct.Add(entry.Id, entry);
}
if (storeProduct != null && !listStoreProduct.TryGetValue(storeProduct.Id, out var procInstance))
{
listStoreProduct.Add(procInstance.Id, procInstance);
entry.ProcessInstance.Add(procInstance);
}
return entry;
}, splitOn: "ProductId").Distinct().ToList();
I hope I could have helped you.

MVVM Dapper how to save changed collectionitems instantly to database

I've got a question relating the above mentioned topic.
------Using Dapper and Caliburn Micro-----
At the moment im building a mvvm wpf application which displays a list of orders. These orders need some ressources to be allocated so the workprocess can begin.
The list of orders provide a few buttons for each row (order) to start, pause, finish and to set the status of the order like "is material allocated".
Whats a good practise to save changes of the above steps made via the list to database?
When creating the order I simply pass the values via a buttonclick to a method in database access project.
For the moment lets just talk about the UIOrderModel and the property IsAllocated
Once the Button (the ugly beige one) is clicked the following method fires:
public void MatAllocated(UIOrderModel order) {
order.IsMatAllocated = "Y";
order.IsAllocated = true;
order.StatusFlag = MKDataWork.Library.Enums.StatusFlag.allocated;
OrdersBc.Refresh();
}
Since it's workig so far as it should be I'm on the question how to store the Information about the changed status of Allocation in my database. By way of example it would be kinda easy just to fire an update query (sp) in the method above.
The collection and the database should always have the same state of data.
The UiOrderModel:
public class UIOrderModel {
private UIOrderModel UIorder = null;
public int Code { get; set; }
public UIuserModel OrderedByEmp { get; set; }
public int OrderedByEmpPersId { get; set; }
public string OrderedByEmpName { get; set; }
public List<UIAllocationModel> AllocationList {get;set;}
public DateTime OrderDate { get; set; }
public UIDepartmentModel ForDepartment { get; set; }
public string DepartmentName { get; set; }
public DateTime ExpectedFinishDate { get; set; }
public string Project { get; set; }
public string Commission { get; set; }
public string IsMatAllocated { get; set; } = "N";
public bool IsAllocated { get; set; } = false;
public string Additions { get; set; }
public StatusFlag StatusFlag { get; set; }
public decimal? Quantity { get; set; }
public UnitOfMeasures Unit { get; set; }
public UIitemModel Item { get; set; }
public string ItemName { get; set; }
public string ItemCode { get; set; }
public DateTime FinishedDateTime { get; set; }
public UIuserModel FinishedByEmp { get; set; }
public UIOrderModel() { }
public UIOrderModel(Dictionary<string,object> entries) {
int i = 0;
this.UIorder = this;
this.Code = int.TryParse(entries["Code"].ToString(), out i) ? i : 0;
this.OrderedByEmp = (UIuserModel)entries["OrderedByEmp"];
this.OrderedByEmpPersId = ((UIuserModel)entries["OrderedByEmp"]).PersId;
this.ForDepartment = (UIDepartmentModel)entries["SelectedDepartment"];
this.DepartmentName = ((UIDepartmentModel)entries["SelectedDepartment"]).Bezeichnung;
this.ExpectedFinishDate = (DateTime)entries["ExpectedFinishDate"];
this.Quantity = (decimal?)entries["Quantity"];
this.Unit = (UnitOfMeasures)entries["SelectedUnitOfMeasures"];
this.Item = (UIitemModel)entries["Item"];
this.ItemName = ((UIitemModel)entries["Item"]).ItemName;
this.ItemCode = ((UIitemModel)entries["Item"]).ItemCode;
this.StatusFlag = (StatusFlag)entries["StatusFlag"];
this.Project = (string)entries["Project"];
this.Commission = (string)entries["Commission"];
this.Additions = (string)entries["Additions"];
}
public UIOrderModel(int code,string orderedByEmpName, int orderedByEmpPersId, string departmentName, DateTime expectedFinishDate,
decimal? quantity, UnitOfMeasures unit, string itemname, string itemcode, string project, string commission,
StatusFlag statusFlag, string additions)
{
this.UIorder = this;
this.Code = code;
this.OrderedByEmpPersId = orderedByEmpPersId;
this.OrderedByEmpName = orderedByEmpName;
this.DepartmentName = departmentName;
this.ExpectedFinishDate = expectedFinishDate;
this.Quantity = quantity;
this.Unit = unit;
this.ItemName = itemname;
this.StatusFlag = statusFlag;
this.Project = project;
this.Commission = commission;
this.Additions = additions;
}
public void SaveOrder() {
OrderModel result = (OrderModel)this;
result.SaveOrder();
}
public static explicit operator OrderModel(UIOrderModel uiOrder) {
return new OrderModel()
{
Code = uiOrder.Code,
OrderDate = uiOrder.OrderDate,
OrderedByEmp = (UserModel)uiOrder.OrderedByEmp,
OrderedByEmpName = $"{uiOrder.OrderedByEmp.FirstName} {uiOrder.OrderedByEmp.LastName}",
ExpectedFinishDate = uiOrder.ExpectedFinishDate,
ForDepartment = (DepartmentModel)uiOrder.ForDepartment,
AllocationList = uiOrder.AllocationList?.Select(am => (AllocationModel)am).ToList(),
IsMatAllocated = uiOrder.IsMatAllocated,
Quantity = uiOrder.Quantity,
Unit = uiOrder.Unit,
Item = (ItemModel)uiOrder.Item,
ItemCode = uiOrder.Item.ItemCode,
ItemName = uiOrder.Item.ItemName,
Project = uiOrder.Project,
Commission = uiOrder.Commission,
StatusFlag = uiOrder.StatusFlag,
Additions = uiOrder.Additions
};
}
public static explicit operator UIOrderModel(OrderModel order) {
return new UIOrderModel()
{
Code = order.Code,
OrderDate = order.OrderDate,
OrderedByEmp = (UIuserModel)order.OrderedByEmp,
OrderedByEmpName = $"{order.OrderedByEmp.FirstName} {order.OrderedByEmp.LastName}",
ExpectedFinishDate = order.ExpectedFinishDate,
ForDepartment = (UIDepartmentModel)order.ForDepartment,
AllocationList = order.AllocationList?.Select(am => (UIAllocationModel)am).ToList(),
IsMatAllocated = order.IsMatAllocated,
Quantity = order.Quantity,
Unit = order.Unit,
Item = (UIitemModel)order.Item,
ItemCode = order.ItemCode,
ItemName = order.ItemName,
Project = order.Project,
Commission = order.Commission,
StatusFlag = order.StatusFlag,
Additions = order.Additions
};
}
}
But whats the correct MVVM way to accomplish this in a proper manner?
Thanks for an advice!
Well I've been on vacation, returned and had some time and distance to the question above. Yesterday I chose a kinda simple way to solve it.
I've implemented the command pattern and passed the execution through my UI project to the data access. It's just one query for all kinds of statussteps (and the relating table) and updates of the whole order. Therefore I pass an enum value (action), orderNo and Id of the employee as parameter for the method / query.
I'm not completely sure if it's the best mvvm way but its working in a comfortable and fast way.

ArgumentNullException: Value cannot be null. (Parameter 'source')

I have parent and childs nested tables.
Here is my model:
public class Categories
{
[Key]
public int CategoriesId { get; set; }
public int Order { get; set; }
public string CategoryName { get; set; }
public List<News> News { get; set; }
}
public class News
{
[Key]
public int NewsId { get; set; }
public int CategoriesId { get; set; }
public string Content { get; set; }
public DateTime Date { get; set; }
...
public List<Comments> Comments { get; set; }
public Categories Categories { get; set; }
}
public class Comments
{
[Key]
public int CommentsId { get; set; }
public int NewsId { get; set; }
public string Comment { get; set; }
...
public News News { get; set; }
}
public class NewsImages
{
[Key]
public int ImageId { get; set; }
public int NewsId { get; set; }
public string ImageUrl { get; set; }
public bool Cover { get; set;}
...
public News News { get; set; }
}
I'm trying to send it from ViewComponent to View;
public async Task<IViewComponentResult> InvokeAsync()
{
var group = _dbContext.Categories.Where(k => k.Order != 0).OrderBy(h => h.Order)
.Select(c => new
{
C = c,
N = c.News.OrderByDescending(n => n.Date).Take(5)
.Select(r => new
{
Y = r.Comments,
R = r.NewsImages.Where(rs => rs.Cover == true).FirstOrDefault()
})
});
var model = group
.Select(m => m.C);
return View(await model.ToListAsync()) ;
}
I am sure there are enough News records for every Category, But I get error :
ArgumentNullException: Value cannot be null. (Parameter 'source')
AspNetCore.Views_Shared_Components_IndexKategori_Default.ExecuteAsync() in Default.cshtml
var bp = k.News.FirstOrDefault();
if I use that code works fine :
var model = _dbContext.Categories
.Include(h => h.News).ThenInclude(h => h.Comments)
.Include(h => h.News).ThenInclude(h => h.NewsImages)
.Where(h => h.Order != 0)
.OrderBy(h => h.Order)
But when I use the code above, a few records appear for some categories, and some categories react as if there are no records.
Where am I making mistakes?
Thank you in advance for those who helped ..
Whenever you have a big LINQ statement that throws an exception, and you can't find where the exception comes form, translate the LINQ into smaller steps, and ToList() every step.
public async Task<IViewComponentResult> InvokeAsync()
{
// Temp code: small steps, ToList after every step
var a = dbContext.Categories.Where(category => category.Order != 0).ToList();
var b = a.OrderBy(category => category.Order).ToList();
var c = b.Select(category => new
{
Category = category,
News = category.News.OrderByDescending(news => news.Date)
.Take(5)
.ToList();
})
.ToList();
var d = c.Select(item => new
{
Category = item.Category,
NewsItems = item.News.Select(news => new
{
Comments = news.Comments,
Images = news.NewsImages.Where(newsImage => newsImage.Cover).ToList(),
})
.ToList(),
})
.ToList();
var e = d.Select(item => new
{
Category = item.Category,
NewsItems = item.NewsItems.Select(newsItem => new
{
Comments = newsItem.Comments,
Images = images.FirstOrDefault();
})
.ToList(),
})
.ToList();
// original code:
var group = _dbContext.Categories.Where...
}
I'm sure that your debugger will tell you which step is incorrect.

Object property is null after taking data from DB. Entity Framework

I have a DBContext that is initializing through DropCreateDatabaseAlways class.
In the Seed method I have this code:
base.Seed(context);
var c1 = new Company { Name = "Samsung"};
var c2 = new Company { Name = "Microsoft"};
context.Companies.AddRange(new List<Company>{c1,c2 });
var phones = new List<Phone>
{
new Phone("Samsung Galaxy S5", 20000, c1),
new Phone("Nokia S1243", 200000, c1),
new Phone("Nokia 930", 10000, c2),
new Phone("Nokia 890", 8900, c2)
};
context.Phones.AddRange(phones);
context.SaveChanges();
And if iterate through phones now, I see that phone.Company is not null.
But when I do this in any other piece of code, phone.Company IS null.
What do I do wrong?
A simple piece of code with null phone.Company:
using (var db = new MyDataModel())
{
var phonesList = db.Phones.ToList();
foreach (var p in phones)
{
System.Console.WriteLine($"Name: {p.Name}
Company: {p.Company}"); // Company is null.
}
}
I can access Company using Join with Companies on phone.companyId, so Companies table exists in DB.
My DataModel class:
public class MyDataModel : DbContext
{
public MyDataModel()
: base("name=MyDataModel")
{
}
static MyDataModel()
{
Database.SetInitializer(new MyContextInializer());
}
public DbSet<Company> Companies { get; set; }
public DbSet<Phone> Phones { get; set; }
}
My Phone class:
namespace DataContext
{
public class Phone
{
public Phone()
{
}
public Phone(string name, int price, Company company)
{
Name = name;
Price = price;
Company = company;
}
public int Id { get; set; }
public string Name { get; set; }
public int Price { get; set; }
public int CompanyId { get; set; }
public Company Company { get; set; }
}
}
If you want to automagically load the companies when you load a phone, you need to add the virtual keyword before the Company property.
public class Phone {
public Phone() {
}
public Phone(string name, int price, Company company)
{
Name = name;
Price = price;
Company = company;
}
public int Id { get; set; }
public string Name { get; set; }
public int Price { get; set; }
public int CompanyId { get; set; }
public virtual Company Company { get; set; }
}
This tells entity framework to automatically load the linked company whenever you retrieve a phone from the database.
Alternatively you can use eager loading when performing a query on phones.
var phones = MyDataModel.Phones.Include(x => x.Company).ToList();
In addition to the cool answer from Immorality, I'll place here these links:
Virtual properties
MSDN - Loading related data strategies

How can I auto-update the int ModifiedBy property on a Entity with UserId in Entity Framework 4 when saving?

I am using Simple Membership and a UserProfile table that maintains UserId and UserName:
public partial class UserProfile
{
public UserProfile()
{
this.webpages_Roles = new List<webpages_Roles>();
}
public int UserId { get; set; }
public string UserName { get; set; }
public virtual ICollection<webpages_Roles> webpages_Roles { get; set; }
}
With Entity Framework I am running the following which is inside my Context:
public partial class UowContext : DbContext
// code to set up DbSets here ...
public DbSet<Content> Contents { get; set; }
private void ApplyRules()
{
var r1 = new Random();
var r2 = new Random();
foreach (var entry in this.ChangeTracker.Entries()
.Where(
e => e.Entity is IAuditableTable &&
(e.State == EntityState.Added) ||
(e.State == EntityState.Modified)))
{
IAuditableTable e = (IAuditableTable)entry.Entity;
if (entry.State == EntityState.Added)
{
e.CreatedBy = // I want to put the integer value of UserId here
e.CreatedDate = DateTime.Now;
}
e.ModifiedBy = // I want to put the integer value of UserId here
e.ModifiedDate = DateTime.Now;
}
}
Here is the schema showing how user information is stored. Note that I store the integer UserId and not the UserName in the tables:
public abstract class AuditableTable : IAuditableTable
{
public virtual byte[] Version { get; set; }
public int CreatedBy { get; set; }
public DateTime CreatedDate { get; set; }
public int ModifiedBy { get; set; }
public DateTime ModifiedDate { get; set; }
}
Here's an example of a controller action that I use:
public HttpResponseMessage PostContent(Content content)
{
try
{
_uow.Contents.Add(content);
_uow.Commit();
var response = Request.CreateResponse<Content>(HttpStatusCode.Created, content);
return response;
}
catch (DbUpdateException ex)
{
return Request.CreateErrorResponse(HttpStatusCode.Conflict, ex);
}
}
I then have:
public class UowBase : IUow, IDisposable
{
public UowBase(IRepositoryProvider repositoryProvider)
{
CreateDbContext();
repositoryProvider.DbContext = DbContext;
RepositoryProvider = repositoryProvider;
}
public IRepository<Content> Contents { get { return GetStandardRepo<Content>(); } }
and:
public class GenericRepository<T> : IRepository<T> where T : class
{
public GenericRepository(DbContext dbContext)
{
if (dbContext == null)
throw new ArgumentNullException("An instance of DbContext is required to use this repository", "context");
DbContext = dbContext;
DbSet = DbContext.Set<T>();
}
public virtual void Add(T entity)
{
DbEntityEntry dbEntityEntry = DbContext.Entry(entity);
if (dbEntityEntry.State != EntityState.Detached)
{
dbEntityEntry.State = EntityState.Added;
}
else
{
DbSet.Add(entity);
}
}
How can I determine the UserId from inside of my Context so I can populate the Id in my tables?
In Code you will have UserName with you through:
HttpContext.Current.User.Identity.Name
you can than query UserProfile table against that Name and get the UserId from there and than assign it to ModifiedBy attribute.
Make sure that you query UserProfile table outside the foreach loop :)

Resources