Using delegate decompiler and comparison in computed properties - entity-framework

I`m using delegate decompiler in my project.
https://github.com/hazzik/DelegateDecompiler
Entity Model (part):
public long Id { get; set; }
public long ItemId { get; set; }
public long InfoItemId { get; set; }
[Computed]
public bool IsInfo
{
get
{
return (InfoItemId > 0 && ItemId == 0) ? true : false;
}
}
AttachmentModel:
private class AttachmentModel
{
public string OriginalFileName { get; set; }
public string ItemFileType { get; set; }
public string Thumbnail { get; set; }
public string File { get; set; }
public string Category { get; set; }
public bool IsInfo { get; set; }
}
Query (part):
Attachments = (from attachments in db.Attachments
where attachments.ItemId == i.Id || attachments.InfoItemId == infoId
select new AttachmentModel
{
OriginalFileName = attachments.ItemOriginalFileName,
ItemFileType = attachments.ItemFileType,
Thumbnail = attachments.FileThumbnailRelative,
File = attachments.FileUrlRelative,
Category = attachments.ItemFileCategory,
IsInfo = attachments.IsInfo.Computed()
}).ToList()
But I got an error:
LINQ to Entities does not recognize the method 'Boolean
ComputedBoolean' method, and this method cannot be
translated into a store expression.
Q: It is possible use delegate decompiler in this case? How?
Please provide some example.

Related

Entity Framwork Update many to many

I am new to ef core. I am trying to implement many to many .
Here is my DBContext
public class MaxCiSDbContext : DbContext
{
public DbSet<Job> Jobs { get; set; }
public DbSet<Staff> Staffs { get; set; }
public MaxCiSDbContext(DbContextOptions<MaxCiSDbContext> options) : base(options)
{
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Job>()
.HasMany(t => t.Staffs)
.WithMany(t => t.Jobs);
base.OnModelCreating(modelBuilder);
}
}
and Here is my Staff Class
public class Staff
{
public string Id { get; set; }
public string Name { get; set; }
public string Email { get; set; }
public string Phone { get; set; }
public string Mobile { get; set; }
public string Address { get; set; }
//Navigation
public virtual ICollection<Job> Jobs { get; set; }
}
Here is my Job Class
public class Job
{
[Key]
public string Id { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public string State { get; set; }
public string ClientOrderNumber { get; set; }
public string StartDate { get; set; }
public string DueDate { get; set; }
public string CompletedDate { get; set; }
public string ClientId { get; set; }
public string ManagerId { get; set; }
public string PartnerId { get; set; }
//Navigation
public virtual ICollection <Staff> Staffs { get; set; }
}
I Call an API which returns a XmlDocument, I read that document and update database.
Here is how I deal with xmldocument.
//Fetch Current Jobs and populate to DB
XmlDocument apiresults = JobMethods.GetCurrent();
XmlNodeList nodes = apiresults.DocumentElement.SelectNodes("/Response/Jobs/Job");
foreach (XmlNode node in nodes)
{
Job MaxCiSJob = new Job()
{
Id = node.SelectSingleNode("ID").InnerText,
Name = node.SelectSingleNode("Name").InnerText,
Description = node.SelectSingleNode("Description").InnerText,
State = node.SelectSingleNode("State").InnerText,
ClientOrderNumber = node.SelectSingleNode("ClientOrderNumber").InnerText,
StartDate = node.SelectSingleNode("StartDate").InnerText,
DueDate = node.SelectSingleNode("DueDate") != null ? node.SelectSingleNode("DueDate").InnerText : "",
CompletedDate = node.SelectSingleNode("CompletedDate") != null ? node.SelectSingleNode("CompletedDate").InnerText : "",
ClientId = node.SelectSingleNode("Client/ID").InnerText,
ManagerId = node.SelectSingleNode("Manager/ID") != null ? node.SelectSingleNode("Manager/ID").InnerText : "",
PartnerId = node.SelectSingleNode("Partner") != null ? node.SelectSingleNode("Partner").InnerText : ""
};
XmlNodeList Assigned = node.SelectNodes("Assigned/Staff");
MaxCiSJob.Staffs = new Collection<Staff>();
foreach (XmlNode staffNode in Assigned)
{
var staffId = staffNode.SelectSingleNode("ID").InnerText;
var staff = _db.Staffs.Find(staffId);
if(staff != null)
{
MaxCiSJob.Staffs.Add(staff);
}
}
if (_db.Jobs.Find(MaxCiSJob.Id) == null)
{
//Insert Record
_db.Jobs.Add(MaxCiSJob);
}
else
{
// UPDATE recorde
_db.Jobs.Update(MaxCiSJob);
}
}
_db.SaveChanges();
}
Everything works well when I run the program for the first time(The linking table ,"JobStaff", is empty) but when I run the Program for the second time I get an excetpion:
SqlException: Violation of PRIMARY KEY constraint 'PK_JobStaff'. Cannot insert duplicate key in object 'dbo.JobStaff'. The duplicate key value is (J14995, 557898).
Can someone please help me on how can I resolve this issue.
Running your code EF core wants to add entities anyway. Because your entities are not attached.
Try this code:
//Fetch Current Jobs and populate to DB
XmlDocument apiresults = JobMethods.GetCurrent();
XmlNodeList nodes = apiresults.DocumentElement.SelectNodes("/Response/Jobs/Job");
foreach (XmlNode node in nodes)
{
var id = node.SelectSingleNode("ID").InnerText;
Job MaxCiSJob = _db.Jobs.Find(id);
if (MaxCiSJob == null)
{
MaxCiSJob = new Job() { Id = id };
_db.Jobs.Add(MaxCiSJob);
}
MaxCiSJob.Name = node.SelectSingleNode("Name").InnerText;
MaxCiSJob.Description = node.SelectSingleNode("Description").InnerText;
MaxCiSJob.State = node.SelectSingleNode("State").InnerText;
MaxCiSJob.ClientOrderNumber = node.SelectSingleNode("ClientOrderNumber").InnerText;
MaxCiSJob.StartDate = node.SelectSingleNode("StartDate").InnerText;
MaxCiSJob.DueDate = node.SelectSingleNode("DueDate") != null ? node.SelectSingleNode("DueDate").InnerText : "";
MaxCiSJob.CompletedDate = node.SelectSingleNode("CompletedDate") != null ? node.SelectSingleNode("CompletedDate").InnerText : "";
MaxCiSJob.ClientId = node.SelectSingleNode("Client/ID").InnerText;
MaxCiSJob.ManagerId = node.SelectSingleNode("Manager/ID") != null ? node.SelectSingleNode("Manager/ID").InnerText : "";
MaxCiSJob.PartnerId = node.SelectSingleNode("Partner") != null ? node.SelectSingleNode("Partner").InnerText : "";
XmlNodeList Assigned = node.SelectNodes("Assigned/Staff");
foreach (XmlNode staffNode in Assigned)
{
MaxCiSJob.Staffs.Clear();
var staffId = staffNode.SelectSingleNode("ID").InnerText;
var staff = _db.Staffs.Find(staffId);
if (staff != null)
{
MaxCiSJob.Staffs.Add(staff);
}
}
}
_db.SaveChanges();
And you should change your domains this way in order not to get NullReferenceException:
public class Staff
{
public string Id { get; set; }
public string Name { get; set; }
public string Email { get; set; }
public string Phone { get; set; }
public string Mobile { get; set; }
public string Address { get; set; }
//Navigation
public virtual ICollection<Job> Jobs { get; set; } = new Collection<Job>();
}
public class Job
{
[Key]
public string Id { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public string State { get; set; }
public string ClientOrderNumber { get; set; }
public string StartDate { get; set; }
public string DueDate { get; set; }
public string CompletedDate { get; set; }
public string ClientId { get; set; }
public string ManagerId { get; set; }
public string PartnerId { get; set; }
//Navigation
public virtual ICollection<Staff> Staffs { get; set; } = new Collection<Staff>();
}

How to get rows of Data from Multiple Tables using LinQ To Entities

I am using dbcontext Code first to get a query base on this condition for the Classes (tables) below:
Creator != null && ArticleAttached != null && !IsCancelled
var ArticleStudentLiked = dbcontext.LearningActivites
.Where(la => la.Creator != null && la.ArticleAttached != null && !la.IsCancelled)
.Sum(la => la.ArticleAttached.StudentsLiked.Count);
var NewsArticleComment = dbcontext.LearningActivites
.Where(la => la.Creator != null && la.ArticleAttached != null && !la.IsCancelled)
.Sum(la => la.ArticleAttached.Comments.Count);
The following Methods only return count for:
ArticleStudentLiked
ArticleComment
I need to get rows of record from the Queries into a single collection which I can pass to View to display line by line
like this :
Article Title, No. of Likes, No. Of Comments
How to use LinQ to Get these : Article Title,No. Of Like , No. of Comment
Classes:
public class LearningActivity
{
public virtual ArticleCreator Creator { get; set; }
public virtual ArticleCreator EditedBy { get; set; }
public virtual Teacher CreatedByTeacher { get; set; }
public virtual Article ArticleAttached { get; set; }
public virtual Article ArticleAttachedByOther { get; set; }
public bool IsCancelled { get; set; }
}
public class Article
{
public string ArticleTitle {get;set;}
public virtual IList<Teacher> TeachersLiked { get; set; }
public virtual IList<Student> StudentsLiked { get; set; }
public virtual IList<ArticleComment> Comments { get; set; }
}
public class Student
{
public virtual IList<ArticleCommentStudent> Comments { get; set; }
}
Thanks
Can you try this
// LikeCount is total of Teacher and Student Likes
// and where clause can be added before Select
var result = dbcontext.Classes
.Select(x=> new { ArticleTitle = x.ArticleTitle,
LikeCount = x.TeachersLiked.Count() + x.StudentsLiked.Count(),
CommentCount= x.Comments.Count }).First();

How to have a nested DTO?

I have this as my entity object:
public partial class RFID_Zones
{
public RFID_Zones()
{
this.RFID_ZonePoints = new HashSet<RFID_ZonePoints>();
}
public int PK_ZoneId { get; set; }
public int PK_FK_ShipId { get; set; }
public string ZoneName { get; set; }
public string Color { get; set; }
public virtual Ship Ship { get; set; }
public virtual ICollection<RFID_ZonePoints> RFID_ZonePoints { get; set;}
}
I am trying to pull all these with this code:
result = _db.RFID_Zones.Where(x => x.PK_FK_ShipId == shipId).Include(x => x.RFID_ZonePoints).ToList();
This works, but I cannot serialize it without getting a circular reference error. Upon Googling I find I should use a Data Transfer Object so I have this:
public class ZoneDto
{
public ZoneDto()
{
this.Zones = new List<RFID_ZonePoints>();
}
public int PK_ZoneId { get; set; }
public int PK_FK_ShipId { get; set; }
public string ZoneName { get; set; }
public string Color { get; set; }
public List<RFID_ZonePoints> Zones { get; set; }
}
And:
var dto = zones.Select(x => new ZoneDto { PK_ZoneId = x.PK_ZoneId, PK_FK_ShipId = x.PK_FK_ShipId,
Color = x.Color, ZoneName = x.ZoneName, Zones = x.RFID_ZonePoints.ToList()});
I still have the issue of the RFID_ZonePoints list. It's a list of a different entity. How can I get those into a data transfer object as well?

Join multiple one to many related tables in EF and select as view model

Database Models of my Application are:
public class Restaurant
{
public int Id { get; set; }
.........
}
public class Review
{
public int Id { get; set; }
public string ReviewTitle { get; set; }
public string ReviewContent { get; set; }
public int UserId { get; set; }
public int RestaurantId { get; set; }
}
public ReviewHelpful
{
public int Id { get; set; }
public int ReviewId { get; set; }
public bool IsHelpfull { get; set; }
}
public ReviewImage
{
public int Id { get; set; }
public string ImageLink { get; set; }
public int ReviewId { get; set; }
}
There is no navigation property in any table. In ReviewHelpful table, If user finds helpfull of this review than value is true otherwise false.
Now I want to create a view-model Like this:
public class ReviewViewModel
{
public int ReviewId { get; set; }
public int RestaurantId { get; set; }
public string ReviewTitle { get; set; }
public string ReviewContent { get; set; }
public int UserId { get; set; }
public int NumberOfHelpfull { get; set; }
public int NumberOfNotHelpfull { get; set; }
public List<string> ImagesLinks { get; set; }
}
For that reason, I want to write this kind of query :
var reviews = (from review in _foodTrackerContext.RestaurantReviews
join helpful in _foodTrackerContext.Helpfuls on review.Id equals helpful.ReviewId
join reviewPicture in _foodTrackerContext.ReviewPictures on review.Id equals reviewPicture.ReviewId
where review.ResturantId == 2
select new ReviewViewModel()
{
Id = review.Id,
RestaurantId = 2,
ReviewTitle = review.ReviewTitle,
ReviewContent = review.ReviewContent,
NumberOfHelpfull = .. ??,
NumberOfNotHelpfull = ... ??,
ImagesLinks = ... ???
}
I can not retrieve HelpfulYes, HelpfulNo, ImagesLinks with this query. What would be query for finding these variables?.
This query produces multiple rows for single review with each ReviewImage and each ReviewHelpful.
The query that ypu need to do is this one:
var model =
from review in ctx.Reviews
where review.RestaurantId == 2
join helpful in ctx.ReviewHelpfuls
on review.Id equals helpful.ReviewId into helpfuls
join image in ctx.ReviewImages
on review.Id equals image.ReviewId into images
select new RestaurantReviewViewModel
{
Id = review.Id,
RestaurantId = 2,
ReviewTitle = review.ReviewTitle,
ReviewContent = review.ReviewContent,
NumberOfHelpfull = helpfuls.Count(h => h.IsHelpfull),
NumberOfNotHelpfull = helpfuls.Count(h => !h.IsHelpfull),
ImagesLinks = (from image in images select image.ImageLink).ToList()
};
Please, note that when you do a one to manyh join you need to include an into to give a nameto the joined entities to be able to work on them.
I've used the dot syntax for selecting the count, but you could use the query syntax if you wanted. Over time, I've found dot synatx more natural.
NOTE: if you used navigation properties this would become much easier. Why are you not using them? With navigation properties you don't need to make the joins explicitly, as they are already available.
List<ReviewViewModel> listModel = new List<ReviewViewModel>();
context.dbRestaurant
.include("Review")
.include("Review.ReviewHelpful")
.include("Review.ReviewImage").ToList().ForEach((item) =>
{
ReviewViewModel model = new ReviewViewModel();
model.ID = item.ID
listModel.Add(model);
});

EF code first property not mapped

The problem I'm encountering is when I try to insert a new record in a ASPxGridView which is a master of detail in an asp.net page.
This only occurs when adding a new record is required when there is no record.
EnderecoEscola entity:
namespace DAL
{
[Table("CAD_ENDERECO_ESCOLA")]
public class EnderecoEscola
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int ENDESC_ID { get; set; }
[Required]
public int ESCOLA_ID { get; set; }
[Association("Escolas", "ESCOLA_ID", "ESCOLA_ID")]
[ForeignKey("ESCOLA_ID")]
public virtual Escola Escola { get; set; }
[Required]
public int TPOEND_ID { get; set; }
[ForeignKey("TPOEND_ID")]
public virtual TipoEndereco TipoEndereco { get; set; }
[Required]
public int ENDESC_UF_ID { get; set; }
[ForeignKey("ENDESC_UF_ID")]
public virtual UnidadeFederativa UnidadeFederativa { get; set; }
[Required]
public int ENDESC_MUN_iD { get; set; }
[ForeignKey("ENDESC_MUN_iD")]
public virtual Municipio Municipio { get; set; }
[StringLength(10), Required]
[MinLength(8)]
public string ENDESC_CEP { get; set; }
[StringLength(100), Required]
[MinLength(10)]
public string ENDESC_ENDERECO { get; set; }
[StringLength(15)]
public string ENDESC_NRO { get; set; }
[StringLength(25)]
public string ENDESC_COMPL { get; set; }
[StringLength(70)]
public string ENDESC_BAIRRO { get; set; }
[NotMapped]
public String TPEND_DESCRICAO { get; set; }
[NotMapped]
public String UF_SIGLA { get; set; }
[NotMapped]
public String MUN_DESCRICAO { get; set; }
}
}
DAL :
namespace DAL.utilities
{
public class OperationCadEnderecoEscola
{
public IQueryable<EnderecoEscola> GetId(int idEsc)
{
using (SecurityCtx ctx = new SecurityCtx())
{
ctx.Configuration.LazyLoadingEnabled = false;
var query = ctx.EnderecoEscola.Include("TipoEndereco").Include("UnidadeFederativa").Include("Municipio").Where(w => w.ESCOLA_ID == idEsc).OrderBy(p => p.ENDESC_ENDERECO).ToList().
Select(w => new EnderecoEscola
{
ENDESC_ID = w.ENDESC_ID,
ESCOLA_ID = w.ESCOLA_ID,
TPOEND_ID = w.TPOEND_ID,
ENDESC_UF_ID = w.ENDESC_UF_ID,
ENDESC_MUN_iD = w.ENDESC_MUN_iD,
ENDESC_CEP = w.ENDESC_CEP,
ENDESC_ENDERECO = w.ENDESC_ENDERECO,
ENDESC_NRO = w.ENDESC_NRO,
ENDESC_COMPL = w.ENDESC_COMPL,
ENDESC_BAIRRO = w.ENDESC_BAIRRO,
TPEND_DESCRICAO = w.TipoEndereco.TPEND_DESCRICAO != null ? w.TipoEndereco.TPEND_DESCRICAO : w.TPEND_DESCRICAO,
UF_SIGLA = w.UnidadeFederativa.UF_SIGLA != null ? w.UnidadeFederativa.UF_SIGLA : w.UF_SIGLA,
MUN_DESCRICAO = w.Municipio.MUN_DESCRICAO != null ? w.Municipio.MUN_DESCRICAO : w.MUN_DESCRICAO
}).Distinct().AsQueryable();
return query;
}
}
}
}
When applying for inclusion in ASPxGridView a new record and the method in DAL public IQueryable <EnderecoEscola> getId (int idEsc) is invoked to retrieve the data and they do not exists it is adding a new record on the master and detail occurs error
A field or property with name 'TPEND_DESCRICAO' was not found in the
selected data source.
Someone could guide me on how to solve the problem.
Tks.