C# 从查询结果在三元运算符中创建对象
我需要创建从数据库中获取的数据返回到前端的对象,因为响应不包含实体的所有字段,而且我还向响应中添加了这个[NotMapped]属性C# 从查询结果在三元运算符中创建对象,c#,entity-framework,C#,Entity Framework,我需要创建从数据库中获取的数据返回到前端的对象,因为响应不包含实体的所有字段,而且我还向响应中添加了这个[NotMapped]属性AmountOfTenants=t.plant.Tenants.Count(), 如果我在这里删除三元运算符t.ApartmentId!=空?并且每次只创建新公寓,然后,当租户没有任何与他相关的Apartmetn时,我的json响应包含租户,他内部有一个公寓对象,其中所有值都是0/null,这就是为什么我需要三元组,如果租户的ApartmentId为空,则将公寓设置为
AmountOfTenants=t.plant.Tenants.Count(),
如果我在这里删除三元运算符t.ApartmentId!=空?
并且每次只创建新公寓
,然后,当租户没有任何与他相关的Apartmetn时,我的json响应包含租户,他内部有一个公寓对象,其中所有值都是0/null,这就是为什么我需要三元组,如果租户的ApartmentId
为空,则将公寓设置为空。
如果没有三元运算符,它可以工作,但我得到的单位值为0/null,当我添加三元运算符时,我得到以下错误:
System.InvalidCastException:无法将“System.Linq.Expressions.NewExpression”类型的对象强制转换为“System.Linq.Expressions.MethodCallExpression”。
请帮忙
List<Tenant> tenants = await _context.Tenants.Include(tenant => tenant.Apartment.House)
.Select(t => new Tenant
{
Id = t.Id,
FirstName = t.FirstName,
LastName = t.LastName,
PersonalCode = t.PersonalCode,
Birthday = t.Birthday,
PhoneNumber = t.PhoneNumber,
Email = t.Email,
ApartmentId = t.ApartmentId,
Apartment = t.ApartmentId != null ? new Apartment
{
Id = t.Apartment.Id,
Number = t.Apartment.Number,
Floor = t.Apartment.Floor,
AmountOfTenants = t.Apartment.Tenants.Count(),
AmountOfRooms = t.Apartment.AmountOfRooms,
TotalArea = t.Apartment.TotalArea,
AvailableArea = t.Apartment.AvailableArea,
HouseId = t.Apartment.HouseId,
House = t.Apartment.House
} : null
}).ToListAsync();
--------------------------编辑
有人要公寓舱:
namespace RestApi.Models
{
public class Apartment
{
public long Id { get; set; }
public int Number { get; set; }
public int Floor { get; set; }
public int AmountOfRooms { get; set; }
[NotMapped]
public int AmountOfTenants { get; set; }
public int TotalArea{ get; set; }
public int AvailableArea { get; set; }
public long? HouseId { get; set; }
public House House { get; set; }
public ICollection<Tenant> Tenants { get; set; }
}
}
在他的机器上,这个
new
语句在另一个new
语句中工作并且没有错误您可以尝试使用它,这样就不需要使用NotMapped
注释,您也不需要在该点使用select
public class Apartment
{
public long Id { get; set; }
public int Number { get; set; }
public int Floor { get; set; }
public int AmountOfRooms { get; set; }
public int AmountOfTenants { get { return this.Tenants != null ? this.Tenants.Count : 0; } }
public int TotalArea { get; set; }
public int AvailableArea { get; set; }
public long? HouseId { get; set; }
public House House { get; set; }
public ICollection<Tenant> Tenants { get; set; }
}
公寓房
{
公共长Id{get;set;}
公共整数{get;set;}
公共整数层{get;set;}
公共int amountofroms{get;set;}
public int AmountOfTenants{get{返回this.Tenants!=null?this.Tenants.Count:0;}
公共整数总面积{get;set;}
公共int可用ea{get;set;}
公共long?HouseId{get;set;}
酒店{get;set;}
公用ICollection租户{get;set;}
}
新查询
List<Tenant> tenants = await _context.Tenants.Include(tenant => tenant.Apartment).ThenInclude(a => a.House).ToListAsync();
List tenants=await\u context.tenants.Include(tenant=>tenant.partment).然后Include(a=>a.House.tolistSync();
编辑
至于你得到的错误的解释。它基本上是说它不能在
新的表达式中创建新的
表达式(即在新租户
中创建新公寓
)我正在对你的公寓类做一个假设,如果我在这里误入歧途,请纠正我。
假设:一个租户只能有一个公寓,而一个公寓可以有多个租户
话虽如此,您的租户类只需要引用一个公寓对象。公寓ID包含在公寓对象中,因此您实际上要将该数据存储两次。如果您希望向公寓中添加新租户,则不需要select语句。如果还有更多,你可能想做一个要点总结来澄清你的意图。如果您希望包含租户类中的所有对象(来自其他表的数据),如果应用程序允许,可以考虑懒惰加载。
public class Tenant
{
[Key]
public long Id { get; set; } //Primary Key
public string FirstName { get; set; }
public string LastName { get; set; }
public string PersonalCode { get; set; }
public DateTime Birthday { get; set; }
public string PhoneNumber { get; set; }
public string Email { get; set; }
//public long? ApartmentId { get; set; }
public virtual Apartment Apartment { get; set; }
}
public class Apartment
{
[Key]
public Guid ApartmentID { get; set; } //Primary Key
public virtual List<Tenant> Tenants { get; set; }
}
public class appStuff
{
void AddStuff()
{
var myContext = new _context();
Apartment apartment = myContext.Find(Predicate4YourApartment());
var ten = new Tenant
{
Birthday = DateAndTime.Now,
Apartment = apartment,
FirstName = "John" //add the rest.
};
myContext.TenantsTable.Add(ten);
//This will add the Tenant to the Tenants table and the apartment to the Apartments table if you create a new one
//instead of finding an existing one like shown above
myContext.SaveChanges();
}
void GetStuff()
{
var myContext = new _context();
var myTenant = myContext.TenantsTable.Where(x => x.Apartment.ApartmentID == "DesiredID");
}
}
public class _context : DbContext
{
public _context() : base()
{
}
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.UseLazyLoadingProxies();
base.OnConfiguring(optionsBuilder);
}
}
公共类租户
{
[关键]
公共长Id{get;set;}//主键
公共字符串名{get;set;}
公共字符串LastName{get;set;}
公共字符串个人代码{get;set;}
公共日期时间生日{get;set;}
公共字符串PhoneNumber{get;set;}
公共字符串电子邮件{get;set;}
//公共long?ApartmentId{get;set;}
公共虚拟公寓{get;set;}
}
公寓房
{
[关键]
公共Guid ApartmentID{get;set;}//主键
公共虚拟列表租户{get;set;}
}
公共类应用程序
{
void AddStuff()
{
var myContext=new_context();
公寓=myContext.Find(predicate4yourpartment());
var ten=新租户
{
生日=日期和时间。现在,
公寓,
FirstName=“John”//添加其余部分。
};
myContext.TenantsTable.Add(十);
//这将在创建新租户时,将租户添加到租户表,并将公寓添加到公寓表
//而不是像上面所示找到一个现有的
myContext.SaveChanges();
}
void GetStuff()
{
var myContext=new_context();
var myTenant=myContext.TenantsTable.Where(x=>x.partment.ApartmentID==“DesiredID”);
}
}
公共类上下文:DbContext
{
public_context():base()
{
}
配置时受保护的覆盖无效(DBContextOptions Builder Options Builder)
{
optionsBuilder.UseLazyLoadingProxies();
基本配置(选项生成器);
}
}
你能分享你的租户类吗?不确定我是否遗漏了什么,但你为什么还要使用选择
?来添加t.plant.Tenants.Count(),
而不在db中维护此列,不添加+1或删除-1当我将租户添加到公寓并选择公寓的属性返回前端时,我可以查看您的公寓类吗?我有一个想法,这可能会奏效。将类更改为您的版本并使用您的查询将导致此错误检测到一个不受支持的可能的对象循环。这可能是由于循环造成的,或者如果对象深度大于允许的最大深度32。
如预期。原因查询租户时将查询公寓,公寓中有租户等forthAh,System.Text.Json
对引用循环处理有限制。因为它不支持它。为了让我的代码正常工作,您必须使用类似于Newtonsoft.Json
,它支持引用循环处理。谢谢。添加了Newtonsoft,现在它可以工作了,但是返回的是空数组而不是无限循环,所以每次都会发送未使用的值。如果你对原始帖子中的错误有一个想法,那么很高兴知道它是什么。不过现在要用你的解决方案。谢谢,我知道错在哪里
List<Tenant> tenants = await _context.Tenants.Include(tenant => tenant.Apartment).ThenInclude(a => a.House).ToListAsync();
public class Tenant
{
[Key]
public long Id { get; set; } //Primary Key
public string FirstName { get; set; }
public string LastName { get; set; }
public string PersonalCode { get; set; }
public DateTime Birthday { get; set; }
public string PhoneNumber { get; set; }
public string Email { get; set; }
//public long? ApartmentId { get; set; }
public virtual Apartment Apartment { get; set; }
}
public class Apartment
{
[Key]
public Guid ApartmentID { get; set; } //Primary Key
public virtual List<Tenant> Tenants { get; set; }
}
public class appStuff
{
void AddStuff()
{
var myContext = new _context();
Apartment apartment = myContext.Find(Predicate4YourApartment());
var ten = new Tenant
{
Birthday = DateAndTime.Now,
Apartment = apartment,
FirstName = "John" //add the rest.
};
myContext.TenantsTable.Add(ten);
//This will add the Tenant to the Tenants table and the apartment to the Apartments table if you create a new one
//instead of finding an existing one like shown above
myContext.SaveChanges();
}
void GetStuff()
{
var myContext = new _context();
var myTenant = myContext.TenantsTable.Where(x => x.Apartment.ApartmentID == "DesiredID");
}
}
public class _context : DbContext
{
public _context() : base()
{
}
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.UseLazyLoadingProxies();
base.OnConfiguring(optionsBuilder);
}
}