I have two entities : Article and PrixVariation.
One Article has Many Prix variation.
One Prix variation has One Article.
public partial class Article
{
public Article()
{
PrixVariations = new HashSet<PrixVariation>();
}
public int Id { get; set; }
public DateTime DateTime { get; set; }
...
public virtual ICollection<PrixVariation> PrixVariations { get; set; }
}
public partial class PrixVariation
{
public int Id { get; set; }
public DateTime DateTime { get; set; }
public int Article { get; set; }
public double Prix { get; set; }
public virtual Article ArticleNavigation { get; set; } = null!;
}
My Context is as follow :
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Article>(entity =>
{
entity.ToTable("articles");
entity.Property(e => e.Id).HasColumnName("id");
entity.Property(e => e.DateTime)
.HasColumnType("datetime")
.HasColumnName("dateTime")
.HasDefaultValueSql("(getdate())");
});
modelBuilder.Entity<PrixVariation>(entity =>
{
entity.ToTable("prix_variation");
entity.Property(e => e.Id)
.ValueGeneratedNever()
.HasColumnName("id");
entity.Property(e => e.Article).HasColumnName("article");
entity.Property(e => e.DateTime)
.HasColumnType("datetime")
.HasColumnName("dateTime")
.HasDefaultValueSql("(getdate())");
entity.Property(e => e.Prix).HasColumnName("prix");
entity.HasOne(d => d.ArticleNavigation)
.WithMany(p => p.PrixVariations)
.HasForeignKey(d => d.Article)
.OnDelete(DeleteBehavior.ClientSetNull)
.HasConstraintName("FK_prix_variation_articles");
});
And my controller is as follow :
public class ArticlesController : ControllerBase
{
private readonly STGEORGESContext _context;
public ArticlesController(STGEORGESContext context)
{
_context = context;
}
// GET: api/Articles
[HttpGet]
public async Task<ActionResult<IEnumerable<Article>>> GetArticles()
{
return await _context.Articles.ToListAsync();
}
....
There is something not working here because when I launch the debogger, the collection of PrixVaration is always empty :
{"id":1,"dateTime":"2021-11-28T08:37:17","prixVariations":[]}
And of course in the database there is one PrixVaration linked to that Article..
Can anyone can help ?? Thaks a lot !!!
Pierre
It is called lazy loading. Ef doesn't load any object collections if you don't ask about it explicitly. So try this
return await _context.Articles.Include(i=> i.PrixVariations).ToListAsync();
Related
I've an application in Asp.NET Core 3.1 MVC with EF Core and Identity.
I've two tables Calls and AspNetUsers. AspNetUsers has many Calls and one Call has one AspNetUsers.
The Calls table structure is okay, I think. But now I need to get Calls from AspNetUsers.
In CallsController I'm trying: IList<Call> calls = this.User.Calls; but no success.
I tried:
IList<Call> calls = this._context.Calls.Where(x => x.UserId == this._userManager.GetUserId(this.User)).ToList();
I've success. But do it is correct?
So, in application i've identity classes and an ApplicationUser like this:
public class ApplicationUser : IdentityUser
{
public virtual IList<Call> Calls { get; set; }
}
And in Startup class in ConfigureServices method:
services.AddDefaultIdentity<ApplicationUser>(options =>
options.SignIn.RequireConfirmedAccount = true)
.AddEntityFrameworkStores<ApplicationDbContext>();
So, What's the better way to get Calls from AspNetUsers? Thanks!
You can set ApplicationUser like :
public class ApplicationUser : IdentityUser
{
public virtual ICollection<Call> Calls { get; set; }
}
Call.cs:
public class Call
{
public int ID { get; set; }
public string name { get; set; }
// other properties
public string UserID { get; set; }
[ForeignKey("UserID")]
public virtual ApplicationUser ApplicationUser { get; set; }
}
In ApplicationDbContext , add :
public virtual DbSet<Call> Calls { get; set; } //add this line
public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options)
: base(options)
{
}
Then you can query the current user's call by :
if (User.Identity.IsAuthenticated)
{
var userID = User.Claims.FirstOrDefault(x => x.Type == ClaimTypes.NameIdentifier).Value;
var calls = _applicationDbContext.Users.Include(u => u.Calls).First(u => u.Id == userID).Calls.ToList();
//or
var callsa = _applicationDbContext.Calls.Where(p => p.UserID == userID).ToList();
}
ApplicationUser should be
public class ApplicationUser : IdentityUser
{
public virtual ICollection<Call> Calls { get; set; }
}
Call entity should be
public class Call
{
public int ID { get; set; }
//...
public string ApplicationUserId { get; set; }
[ForeignKey(nameof(ApplicationUserId))]
public virtual ApplicationUser ApplicationUser { get; set; }
}
and, of course, you should override the OnModeCreating method in your DbContext like this
public class ApplicationDbContext: DbContext
{
public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options)
: base(options){}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Entity<Call>()
.HasOne(x => x.ApplicationUser)
.WithMany(x => x.Calls);
}
//...DbSets..
}
and finally, load all your calls in Calls collection of ApplicationUser
var user = await _context.ApplicationUsers.FindAsync(_userManager.GetUserId(this.User));
await context.Entry(user)
.Collection(x => x.Calls)
.LoadAsync();
Now, you have all your calls loaded in Calls collection of the current user.
I created two classes:
public class A {
public int Id { get; set; }
public ICollection<B> Bs { get; set; }
}
public class B {
public ICollection<C> C1s { get; set; }
public ICollection<C> C2s { get; set; }
}
then I tried to fetch them with ThenInclude method:
var result = context.As //public DbSet<A> As { get; set; }
.Include(a => a.Bs)
.ThenInclude(b => b.C1s)
.Include(a => a.Bs)
.ThenInclude(b => b.C2s)
.SingleOrDefaultAsync(a => a.Id.Equals(id)); //id is given
return await result;
But unfortunately both C1s and C2s collections are empty.
How to retrieve C entities which are related to B one?
I replaced .ThenInclude() methods with
.Include("Points.MasterPoints")
.Include("Points.SlavePoints")
That solved my issue.
I'm having two classes - author and blogpost:
public class Author
{
public Author()
{
Blogposts = new HashSet<Blogpost>();
}
public int Id { get; set; }
public string Name { get; set; }
public virtual ICollection<Blogpost> Blogposts { get; set; }
}
and
public class Blogpost
{
public Blogpost()
{
}
// Properties
public int Id { get; set; }
public string Text { get; set; }
public int AuthorId { get; set; }
public Author Author { get; set; }
}
Using EF7 (beta4), I'm connecting them the following way:
public partial class MyDbContext : DbContext
{
public virtual DbSet<Author> Author { get; set; }
public virtual DbSet<Blogpost> Blogpost { get; set; }
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Author>(entity =>
{
entity.Property(e => e.Id)
.ForSqlServer().UseIdentity();
});
modelBuilder.Entity<Blogpost>(entity =>
{
entity.Property(e => e.Id)
.ForSqlServer().UseIdentity();
});
modelBuilder.Entity<Blogpost>(entity =>
{
entity.Reference<Author>(d => d.Author).InverseCollection(p => p.Blogposts).ForeignKey(d => d.AuthorId);
});
}
}
When I access a blogpost Db.Blogpost.First(x => x.Id == id) I retrieve the Blogpost object - however, the .Author property is null. Also, when retrieving any Author object, it's .Blogposts collection is empty.
I understand the EF7 has neither implemented eager-loading nor lazy-loading yet. But how would I then retrieve/assign any objects referenced via foreign key?
EF 7 has implemented eager loading.
Use .Include
var post = context.Blogpost.First(); // post.Author will be null
var post = context.Blogpost.Include(b => b.Author).First(); // post.Author will be loaded
For more information on working with collections, see the answer to this question: How to work with collections
I cant get to work my grid using telerik
here's my code:
MODEL
public class Office
{
public int OfficeID { get; set; }
public string OfficeName { get; set; }
public string OfficeAddress { get; set; }
}
VIEWMODEL
public class OfficeViewModel
{
public int OfficeID { get; set; }
public string OfficeName { get; set; }
public string OfficeAddress { get; set; }
}
VIEW
#(Html.Telerik().Grid<Office>()
.Name("Offices")
.ToolBar(tb => tb.Insert())
.DataBinding(binding => binding.Ajax()
.Select("GetOffice", "Office")
.Update("UpdateOffice", "Office")
.Insert("InsertOffice", "Office")
.Delete("DeleteOffice", "Office"))
.DataKeys(keys => keys.Add(o => o.OfficeID))
.Columns(cols =>
{
cols.Bound(c => c.OfficeID).ReadOnly();
cols.Bound(c => c.OfficeName).Width(20);
cols.Bound(c => c.OfficeAddress).Width(70);
cols.Command(cmd =>
{
cmd.Edit();
cmd.Delete();
});
})
)
CONTROLLER
public ActionResult Index()
{
ViewBag.Message = "Welcome to ASP.NET MVC!";
return View();
}
[GridAction]
public ActionResult GetOffices()
{
return View(new GridModel(GetOfficeViewModels()));
}
private IQueryable<OfficeViewModel> GetOfficeViewModels()
{
return db.Offices
.Select(
c => new OfficeViewModel
{
OfficeID = c.OfficeID,
OfficeName = c.OfficeName,
OfficeAddress = c.OfficeAddress
});
}
LASTLY, THE LAYOUT.
<li>#Html.ActionLink("Office", "Index", "Office")</li>
please help me solve this problem i have already spent many hours on this. I'm only a beginner :(
Thanks
It's fixed now, it should be
.Select("GetOffices", "Office")
I missed the 's', sorry I'm new at this telerik thing
Thanks
I Upgrade my NHibernate for 3.1.0.4000 and Fluent for 1.2.0.712 and have some problems with HasMany...
my entities:
public class MateriaPrima
{
public virtual int Id { get; set; }
public virtual string Description { get; set; }
public virtual DateTime Date { get; set; }
public virtual decimal Price { get; set; }
}
public class Product
{
public virtual int Id { get; set; }
public virtual IList<ProductMateriaPrima> ListMateriaPrima { get; set; }
public virtual string Description { get; set; }
public virtual decimal Price { get; set; }
public virtual DateTime Date { get; set; }
public Product()
{
this.ListaMateriaPrima = new List<ProductMateriaPrima>();
}
}
public class ProductMateriaPrima
{
public virtual int Id { get; set; }
public virtual Product Product {get;set;}
public virtual MateriaPrima MateriaPrima { get; set; }
public virtual decimal PrecoCusto {get;set;}
}
And Maps:
public class MateriaPrimaMap : ClassMap<MateriaPrima>
{
public MateriaPrimaMap()
{
Id(m => m.Id).Length(11).Not.Nullable();
Map(m => m.Description).Length(90).Not.Nullable();
Map(m => m.Date).Not.Nullable();
Map(m => m.Price).Not.Nullable();
}
}
public class ProductMateriaPrimaMap : ClassMap<ProductoMateriaPrima>
{
public ProductMateriaPrimaMap()
{
Id(c => c.Id).Length(11);
Map(c => c.Price).Not.Nullable();
References(c => c.MateriaPrima).Column("IdMateriaPrima").Not.LazyLoad();
References(c => c.Product).Column("IdProduct").Not.LazyLoad();
}
}
public class ProdutoMap : ClassMap<Produto>
{
public ProdutoMap()
{
Id(m => m.Id).Length(11).Not.Nullable();
Map(m => m.Description).Length(90).Not.Nullable();
Map(m => m.Price).Length(10);
Map(m => m.Date).Length(12);
Map(m => m.Active).Not.Nullable();
HasMany(x => x.ListaMateriaPrima)
.Table("ProdutoMateriaPrima")
.KeyColumn("IdProduto")
.KeyColumn("IdMateriaPrima")
.Inverse()
.Cascade.AllDeleteOrphan();
}
}
When i try to search, i got the error: {"Unknown column 'listamater0_.MateriaPrima_id' in 'field list'"}
This error don´t happen when i had the old version of Nhibernate and Fluent...
Someone know what´s happening?
Thanks for the help...
This error happend because you didn't set collumn name of Id property, default pattern for id is: entityname_id.
And now in ProductMateriaPrimaMap class you wrote:
References(c => c.MateriaPrima).Column("IdMateriaPrima")
This mean that in you MateriaPrimaMap class you should have Id with collumn name: IdMateriaPrima, but default you have name: MateriaPrima_Id.
I can't say where the problem is exactly because you didn't show the query. But i know that this error happend when Id column name is diffrent from Reference column name.