Updating navigation property works but entity does not appear in Collection - c#

I've got 2 entities, User and Material. User holds the Collection of the materials.
public class User
{
...
private ICollection<Material> materials;
public virtual ICollection<Material> Materials
{
get { return materials ?? (materials = new List<Material>()); }
set { materials = value; }
}
}
And material:
public class Material
{
...
public int? UserId { get; set; }
public virtual User User { get; set; }
...
}
When logged User selects Material, I assign that User to Material.User and save changes. Works fine, changes are saved in db. But, if I want to access materials with User.Materials, collection contains no elements. I have tried with simple project and there it works. With my complex project, it does not. What to do?
Help me please, bothering with problem for 8 hours already and still havent fix it.
EDIT: Well, that is so... lame.
My code was actually working BUT... the problem was, when view-ing user details, I retrieved User from database and created a COPY of it with a cunstrictor. I was missing something:
public User(User otherUser)
{
Id = otherUser.Id;
FirstName = otherUser.FirstName;
LastName = otherUser.LastName;
Shift = otherUser.Shift;
PassCode = otherUser.PassCode;
Type = otherUser.Type;
Materials = otherUser.Materials; // this line was missing
}
After adding this line, it works. Just Visual Studio is complaining about that (virtual member call in constructor). What to do about it?

Your problem are here:
private ICollection<Material> materials;
public virtual ICollection<Material> Materials
{
get { return materials ?? (materials = new List<Material>()); }
set { materials = value; }
}
Entity Framework navigation property cannot be property with backing field. It can be only autoproperty. So you should use this code instead:
public class User
{
...
public virtual ICollection<Material> Materials
{
get;
set;
}
}

Related

Backendless c# desktop application saving data but by empty or null values

I have a desktop app written in c# and I added app id and key id
and used this code to add data to database but the data is always empty or null.
var film = new Film();
film.setName(“soooft”);
film.setGenre(“aaa”);
film.setPlot(“fdgveqw”);
film.setUrl(“gdfwrw”);
var f = Backendless.Data.Of<Film>().Save(film);
I googled Backendless and it's a third-party solution. (See https://github.com/Backendless/.NET-SDK)
Usage gets explained at https://backendless.com/docs/dotnet/data_data_object.html
But I'm suspicious about why you use setName(), setGenre(), setPlot and setUrl in your code. Seems your Film class is missing properties. I would expect you'd be writing this instead:
var film = new Film();
film.Name = “soooft”;
film.Genre = “aaa”;
film.Plot = “fdgveqw”;
film.Url = “gdfwrw”;
But that would mean those fields are declared as public properties in your class like this:
public class Film
{
public string Name { get; set; }
public string Genre { get; set; }
public string Plot { get; set; }
public string Url { get; set; }
}
So I don't know why you have those setName and other methods. The Backendless API specifies that these fields need to be public properties so it can read them through reflection. Your code seems to suggests that they're not proper properties as indicated by their example and my code of the Film() class.
Make sure to use public get/set properties instead of private fields and the data will be saved properly.

Entity Framework not saving all properties on update

I am trying to update an entity with custom getters and setters but they are not being saved if I edit any other property on the entity. I have a DTO, which maps onto the retrieved entity.
DTO:
public class MyEntityDto
{
public string Id { get; set; }
public string Name { get; set; }
public bool Enabled { get; set; }
public Dictionary<string, string> Settings { get; set; }
}
Entity:
public class MyEntity
{
public virtual Guid Id { get; set; }
public virtual string Name { get; set; }
public virtual bool Enabled { get; set; }
public Dictionary<string, string> Settings { get; set; }
public virtual string SettingsJson
{
get { return JsonConvert.SerializeObject(Settings); }
set
{
Settings = JsonConvert.DeserializeObject<Dictionary<string, string>>(value);
}
}
}
Update Function:
public async Task UpdateAsync(dto MyEntityDto)
{
var existingEntity = await _myRepository.GetByIdAsync(dto.Id);
existingEntity.Name = dto.Name;
existingEntity.Enabled = dto.Enabled;
existingEntity.Settings = dto.Settings;
await _myRepository.Update(existingEntity);
// save changes happens at end of request
}
What happens is my SettingsJson does not get updated. I have stepped through it and existingEntity.SettingsJson and existingEntity.Settings both have the correct data. Name and Enabled do get updated.
However if I remove the assignments for Name and Enabled, SettingsJson does get updated.
It does work however on entity creation, just not on update. I would also like to point out I do not have access to DbContext.
I'm guessing Entity Framework doesn't know it should update SettingsJson in the database because you never modify it directly in your code. Yes, you modify the Settings object which is used in the getter of SettingsJson, but Entity Framework does not track objects that way.
Try this after modifying the Settings object, but before doing the actual update:
_myDbContext.Entry(existingEntity).Property(e => e.SettingsJson).IsModified = true;
This code however assumes your DbContext is exposed, which may not be the case.
EDIT:
If you don't have access to the DbContext, you must directly set the SettingsJson property in order to have Entity Framework update it in the database. I understand that in your current implementation you never need to worry about updating both the actual dictionary and the JSON representation of the dictionary, but that's just not possible with Entity Framework. You'll have to try something like this:
public virtual string SettingsJson { get; set; } // just an auto-implemented property
...
existingEntity.Settings = dto.Settings;
existingEntity.SettingsJson = JsonConvert.SerializeObject(dto.Settings);
// save changes
Another solution could be to directly set the SettingsJson in the setter of Settings, like so:
private Dictionary<string, string> settings // private backing field
public Dictionary<string, string> Settings
{
get { return settings; }
set
{
settings = value;
SettingsJson = JsonConvert.SerializeObject(dto.Settings); // EF tracks this
}
}
However, if you add elements to the dictionary after setting it, you need to re-serialize the dictionary again, in order to update the JSON string. You could solve this dynamically by using some sort of observable dictionary, but make sure it only serializes the dictionary once, when needed (before calling updating the database).
This is not really a solution but it's food for thought. Databases don't understand dictionaries. You know that, that's why you're using JSON to help you out. However, why not simply add a Setting table to your database model?

Accessing a list of objects & how to claim a object for the fatest request

I'm developing an Asp.net mvc project:
There is a List store all the online Pupils
There are few methods:
- Login(Pupil p): if login ok, p will be added to Pupils list
- Logout(Pupil p): if logout ok, p will be removed out of Pupil list
-> 2 methods have a same potential issue is "cannot modify list while modifying" because there are a lot of Pupil login to system and logout at the same time. While adding a pupil the other are being removed from Pupils list -> exception throws
I tried to use lock to lock a list while modifying (insert/remove) but is it a good way to do? Do you have some better idea?
The last method is Claim(Book b)
Administrator put some books in the GUI and all the logged Pupils can see these books. They can claim any book they want. The fastest Pupil claimed is will own that book. So how can we know the fastest claimer? While updating a data row. At the same time there are many books are claimed by many pupils. But only one fastest pupil can own a particular book after claiming successfully
Do you have a solution for this? This solution just like you put a command to buy stocks. The fastest guy will own the stocks
Remember that there are many pupils will do the same thing at the same time. So we have to make sure that system works properly and exactly
Thanks you in advance,
Best regards
The issue I see here is that your design assumes that the application is always on, and that the lists are the absolute truth about who has what book. What happens when the server is reset? What if your library gets big enough to need a second server to the application?
You need to preserve your lists in a database or some other sort of persistent medium. Holding the lists in memory will give you a read/write buffer, but the lists must be populated from the persistence layer of your library database.
using System;
using System.Collections.Concurrent;
namespace TestArea
{
public class Pupil
{
public Guid Id { get; set; }
public string Name { get; set; }
public string UserName { get; set; }
}
public class Book
{
//Supports having more than one ISBN in the library... We may have more than one To Kill a Mockingbird in our school library
public Guid Id { get; set; }
public string ISBN { get; set; }
}
public class SchoolLibrary
{
private ConcurrentDictionary<Guid, Pupil> Pupils { get; set; }
private ConcurrentDictionary<Guid, Book> Books{ get; set; }
private ConcurrentDictionary<Guid, Guid> CheckOuts { get; set; }
public Pupil Login(string userName, string password)
{
//Call repository to authenticate pupil into library system
//Mocked return assuming password check success
var id = Guid.NewGuid();
return Pupils.GetOrAdd(id, (i) =>
{
//Replace with function to get student info
return new Pupil
{
Id = i,
Name = "Bac Clunky",
UserName = userName
};
});
}
public bool CheckOut(Guid pupilId, Guid bookId)
{
//If book exists
if (Books.ContainsKey(bookId))
{
Guid currentOwner;
//...is not currently checked out by anyone
if (CheckOuts.TryAdd(bookId, pupilId))
{
return true; //book is now checked out
}
if (CheckOuts.TryGetValue(bookId, out currentOwner))
{
return currentOwner == pupilId; //returns true if pupil already has the book, false if another student has it
}
}
return false; //all other cases fail to check out book
}
}
}

Wpf - How to control observable collection updates

In the parent there is a Observable Collection PendingPayment that has a list of all pending payments of sales with a column amount paid.
Then the user can select a particular sale and open it in new child window.
The thing thats going wrong is if the user just edits the text box paid amount in child window and closes the window without saving the new paid amount to database,the observable collection containing Amount paid column in the parent window gets updated.
What I want is it the collection to get updated only when the values are updated in the database.
This can be achieved by creating a copy of your sale object when the user select it in the list, and then using this copy as the view model of your child view.
You will then be able to set the new values in the original object from your list only once the save button has been clicked and the database update succeed.
An other way to proceed if you need to edit only few of the object properties would be to create and editor object and use it as the child window's view model.
Something like this :
public class Sale
{
public int PaidAmount { get; set; }
public int Some { get; set; }
public int More { get; set; }
public int Properties { get; set; }
}
public class SaleEditor
{
private Sale _sale;
public int PaidAmount { get; set; }
public SaleEditor(Sale sale)
{
_sale = sale;
PaidAmount = sale.PaidAmount;
}
public void Save()
{
// update your data here
_sale.PaidAmount = PaidAmount;
}
}
If you need your original object to update the database, then the save method could first update the object and the revert the changes if DB update failed :
public void Save()
{
var oldAmount = _sale.PaidAmount;
_sale.PaidAmount = PaidAmount;
if (!SalesDB.Update(_sale))
_sale.PaidAmount = oldAmount;
// you could also read back the value from DB
}
Whenever possible (I've never see a reason why it cannot),for listing purpose use proxy or flatted objects, you can implement this using projections query. Then user select an item from a list and the only thing you need to grab is a key to load the full object with its required object graph as the use case might dictate.
Here is a sample implementation using Entity Framework and c# lambda expressions:
Using anonymous object:
var anonymousListProjection = DbContext.PendingPayments.Select( pp=>
new { pp.Order, pp.Amount})
Using a hardcoded proxy:
var hardcodedListProjection = DbContext.PendingPayments.Select( pp=>
new PendingPaymentProxy { Order = pp.Order, Amount = pp.Amount})
//To return an observable:
var observableColl = new ObservableCollection<PendingPaymentProxy>
(hardcodedListProjection.Tolist());
public class PendingPaymentProxy
{
public string Order { get; set; }
public decimal Amount{ get; set; }
}
Apart from avoiding possibles performance problems due to unintentional loading real objects, this way you only have to worry for your list when the user do save in the detail view.

Entity Framework Code First, nonempty setter or getter?

I am working with an EF Code First project, and all is well. I have a simple Class, Customer. In my Customer Class I have a field I want to encrypt (Yes, I know I can encrypt at the DB level but requirements dictate I encrypt at the Domain/Code level), so I am hoping that I can do something like the following:
public class Customer
{
public int CustomerID { get; set; }
public string FieldToEncrypt { get; set { _FieldToEncrypt = MyEncryptionFunction.Encrypt(); } }
}
However, I assume that if the setter has a definition, entity framework code first may ignore that property when generating the schema. So my question is, is there a way to do EF Code First with provided getters/setters, or should I move this functionality into a constructor? Should I override one of the methods/events that happens when the Context is saving, instead?
EDIT ********************
As a note, I am using DataService to transmit the data over an OData protocol service. This automatically generates insert/update/select methods. Some of the suggestions require creating a second property, but the DataService class does not seem to pass through NotMapped properties. This throws a bit of a kink into my earlier question.
public class Customer
{
public int CustomerID { get; set; }
public string EncryptedField { get; private set; }
[NotMapped]
public string Field
{
get { return MyEncryptionFunction.Decrypt(EncryptedField); }
set { EncryptedField = MyEncryptionFunction.Encrypt(value); }
}
}

Categories