Entity framework relations - entity-framework

im trying to make an app and got a slight problem. my structure looks like this:
public class BaseModel
{
[Key]
private int _Id;
public int Id {
get { return _Id; }
set { _Id = value; }
}
}
public class SupplierModel : BaseModel
{
[ForeginKey("CountryCode")] // This should map to say "se" or "no" or whatever in the CountryModel table
public virtual CountryModel Country;
}
public class CountryModel : BaseModel
{
private string _CountryCode;
[Key] // This should be another key in the table to get the actual country.
public string CountryCode {
get { return _CountryCode; }
set { _CountryCode = value; }
}
private string _CountryName;
public string CountryName {
get { return _CountryName; }
set { _CountryName = value; }
}
}
Now i want SupplierModel to link to CountryModel (Works fine by the Id) but i want it to be the country code to be the relationship not the Id between the Entities.
So accessing CountryModel.Country should map to the CountryModel table and pull out the one that matches the country model.
Hope i didnt mess it up totaly for you, hard to explain when i do not fully understand Entity framework and database relations .. trying to learn =)

Related

EF Core 6: How to implement controller that returns joined data?

I have a database with several different, but related tables:
class AccountInfo {
string id;
string name;
string email;
}
class ExtraInfo {
string id;
string proxy;
}
class UserInfo {
AccountInfo account;
ExtraInfo extra;
}
public class MyDbContext : DbContext {
public DbSet<AccountInfo> AccountInfo { get; set; }
public DbSet<ExtraInfo> ExtraInfo { get; set; }
}
public class ExtraInfoController : ODataController
{
private readonly DS2DbContext _context;
private readonly ILogger<UserInfoController> _logger;
public ExtraInfoController(DS2DbContext context) {
_context = context;
}
[EnableQuery(PageSize = 15)]
public IQueryable<UserInfo> Get() {
IQueryable<UserInfo> query =
from a in _context.AccountInfo
from x in _context.ExtraInfo
where (a.id == x.id)
select new UserInfo() { account = a, extra = x };
return query;
}
The query in ExtraInfoController.Get() works, but the result cannot be transferred back to the calling code, because the DbSet is declared for type ExtraInfo and I guess because of the way Blazor mangles all the pseudo code passed to it into working code, so it expects the return type to be IQueryable and not IQeryable.
I am new to EF core, so I don't know how to create a controller that is not directly related to a db table that would do the desired join and return an IQueryable without there being a UserInfo table in the db.

EF Context not keeping values after adding entity

Edit Is this post lacking sufficient information to get some guidance?
I have this method to insert an entity into the database:
public void Insert(T entity)
{
_context.Set<T>().Add(entity);
_context.SaveChanges();
}
When I inspect entity before adding it to the context, my CustomerRole field is there. Once the add has taken place, the context doesn't seem to have it. Because of this, I am receiving this error:
Entities in 'CcDataContext.Customers' participate in the
'Customer_CustomerRole' relationship. 0 related
'Customer_CustomerRole_Target' were found. 1
'Customer_CustomerRole_Target' is expected.
These images show what I mean:
Inspecting my entity
Inspecting the context
Can anyone explain this behaviour and what I can do about it?
This is the structure of my classes (cut down for brevity):
public class Customer : BaseEntity
{
public CustomerRole CustomerRole { get; set; }
}
class CustomerMap : EntityTypeConfiguration<Customer>
{
public CustomerMap()
{
HasRequired(t => t.CustomerRole)
.WithMany(t => t.Customers);
}
}
public class CustomerRole : BaseEntity
{
private ICollection<Customer> _customers;
public ICollection<Customer> Customers
{
get { return _customers ?? (new List<Customer>()); }
set { _customers = value; }
}
}
I can confirm that customer map is being added to the configuration and my database is built in line with them.
This is the call I am making which does the insert:
public Customer InsertGuestCustomer()
{
var customer = new Customer();
CustomerRole guestRole = GetCustomerRoleByName("Guest");
if (guestRole == null)
throw new Exception("Customer Role is not defined!");
customer.UserName = "";
customer.EmailAddress = "";
customer.Password = "";
customer.IsAdmin = false;
customer.CustomerRole = guestRole;
_customerRepository.Insert(customer);
return customer;
}
I have no other data in my database, this would be the first customer record and only one CustomerRole. My Customer table has a Foreign Key pointing to my CustomerRole.Id table / column.
Mark your navigation properties as virtual and initialize the collection property in the entity constructor rather than from the property getter.
public class Customer : BaseEntity
{
public virtual CustomerRole CustomerRole { get; set; }
}
...
public class CustomerRole : BaseEntity
{
public CustomerRole()
{
Customers = new List<Customer>();
}
public virtual ICollection<Customer> Customers { get; protected set; }
}
In your Customers property, you were returning a new List in the getter when the backing field was null, but you never assigned this to your backing field.

Value Object persisting via Entity framework

I saw this sample here , here is this suggested way to make vaueobject in DDD , take a look at this
public class SubCategory : ValueObjectBase
{
public string Name { get; private set; }
public int NumberOfPosts { get; private set; }
public SubCategory()
{
}
public SubCategory(string name, int numberOfPost)
{
Name = name;
NumberOfPosts = numberOfPost;
}
}
in my code , I'm using ValueObjectBase that don't let me to have any Id , every table in Entity framework mapping should have an Id to make a table in Database , How can I map this valueObject ann kinda imutable class ???
my mapping calss is like this :
public class SubCategoryMapping : EntityTypeConfiguration<SubCategory>
{
public SubCategoryMapping()
{
ToTable("SubCategory");
// Id ????
Property(sc => sc.Name);
Property(sc => sc.NumberOfPosts);
}
}

MVVM - How to wrap ViewModel in a ViewModel?

First of all, I have read this post and did not find the answer for my problem.
I am not sure if this is an aggregated Model class or an aggregated ViewModel class, but this is what I have:
In my WPF (with Prism) application, I have a view 'Filter Customers View' that connects to a service and requests a list of 'Customer' objects, based on a filter.
The list that is returned from the service is this :
List<CustomerDTO> FilteredCustomers;
And the CustomerDTO looks like this:
public class CustomerDTO
{
public Guid CustomerId;
public String Name;
public String Address;
public String PhoneNumber;
public OrderInfoDTO LastOrderInformation;
public List<OtherClass> ListOfSomething;
}
And the OrderInfoDTO looks like this:
public class OrderInfoDTO
{
public Guid OrderId;
public DateTime OrderDate;
public int NumberOfProducts;
public double TotalAmountSpent;
}
And the OtherClass looks like this:
public class OtherClass
{
public Guid Id;
public String SomeText;
}
As you can see - the customer might or might not have a 'Last Order',
I would like to wrap the 'CustomerDTO' object in a ViewModel,
so that I can bind it to the view.
This is what I thought of doing :
public class CustomerViewModel : NotificationObject
{
private CustomerDTO _customerDTO;
public CustomerViewModel(CustomerDTO customerDTO)
{
_customerDTO = customerDTO;
}
public Guid CustomerId
{
get { return _customerDTO.CustomerId; }
set { _customerDTO.CustomerId = value; RaisePropertyChanged("CustomerId "); }
}
public String Name
{
get { return _customerDTO.Name; }
set { _customerDTO.Name = value; RaisePropertyChanged("Name"); }
}
public String Address
{
get { return _customerDTO.Address; }
set { _customerDTO.Address = value; RaisePropertyChanged("Address"); }
}
public String PhoneNumber
{
get { return _customerDTO.PhoneNumber; }
set { _customerDTO.PhoneNumber= value; RaisePropertyChanged("PhoneNumber"); }
}
}
.
Questions:
First of all - is 'CustomerDTO' what is known as a Model ? And is 'OrderInfoDTO' also a Model ? and what about 'OtherClass' ?
How do I treat the 'OrderInfoDTO' in my CustomerViewModel class ? Do I create a 'ViewModel' for it also ? where do I create the 'OrderInfoDTO' view-model ??? What happens if now someone updates the customer and sets the 'OrderInfoDTO' value ?
How do I treat the list of 'OtherClass' in my CustomerViewModel class ? Do I create an ObservableCollection for it ? What happens if someone will want to delete an item in it or update an item in it or add an item to it ?
Think about it this way:
The View is your UI that you would bind elements from the View Model to using the {Binding Path=, Mode=TwoWay -- If you want to update based upon the user input
The Model is only the data, this could a record set, file, database records etc. So CustomerDTO and OrderInfoDTO are models.
The View Model is your link between the data (Model) and the UI (View). It will allow to you change the data so it's easier to present on the UI
You would need to use ObservableCollection in all instances where there's a list that could change in the background.
You don't need a view model for OrderInfoDTO unless you need a view to update that data. If you are presenting a CustomerDTO info with OrderInfoDTO in it, then making it a property of the CustomerDTO view model would be fine.

what is use of creating property in separate class for each entilty?

I am learning some good code practice that's why i was going through some code, some thing i could not understand in it. It has made property in a separate class for each entity like in userClass it has property
#region public properties
private int uid;
public int userId
{
get { return uid; }
set { uid = value; }
}
private string uName;
public string userName
{
get { return uName; }
set { uName = value; }
}
private string pwd;
public string password
{
get { return pwd; }
// set { pwd = value; }
}
private string uAddress;
public string userAddress
{
get { return uAddress; }
set { uAddress = value; }
}
private string fName;
public string firstName
{
get { return fName; }
set { fName = value; }
}
private string lName;
public string lastName
{
get { return lName; }
set { lName = value; }
}
private string uPhone;
public string userPhone
{
get { return uPhone; }
set { uPhone = value; }
}
private string uMobile;
public string userMobile
{
get { return uMobile; }
set { uMobile = value; }
}
private int secretQuestion;
public int securityQuestion
{
get { return secretQuestion; }
set { secretQuestion = value; }
}
private string userAnswer;
public string answer
{
get { return userAnswer; }
set { userAnswer = value; }
}
#endregion
and from the business logic class it uses the property instead of using directly any entity's attribute name, but i am confuse whats there need to make a property like this?
other then this it has got enums for database column name which has a clear reason behind this that if in near future we have to change the database table's fields name then we don't have to change through out the whole business logic class and we can make changes to enum directly, But what is there use of creating property like this please elaborate me on this
Are you really asking why it uses properties instead of having public fields?
Fields are an implementation detail - they're how data is stored, which shouldn't be something the outside world cares about, at least for 99% of types. Properties are part of the contract that a type has in terms of its API - the implementation is up to the type. In other words, it's a matter of encapsulation. Properties can be expressed in interfaces, as abstract methods etc, precisely because they keep the contract and the implementation separate.
Additionally, properties make databinding, debugging and various other things simpler. I have an article about why properties matter, which you may find useful.
Having said all of this, those properties are implemented in a tedious way - and they don't obey .NET naming conventions. I would have written them as:
public int UserId { get; set; }
public string UserName { get; set; }
public string Password { get; set; }
// etc
Properties can be defined on Interfaces, but member fields cannot. So if you needed to refactor this class to a class that implements an interface, you can put the properties on the interface (and then have other classes that implement them as well.)
Some similar questions:
Public Fields versus Automatic Properties
Property vs public field.
In additional to above: Actually you can easily decide public field or property by yourself. It is quite easier to understand that:
(1) Name is a property of class Person
(2) Speed is a property of class Plane
(3) Empty is a public field of class String. If you say String has a property named Empty, it's really weird. And String has a property Length is easy to understand.