Building lambda expression dynamically - dynamic

I know how to build a simple lambda like x => x > 5:
int[] nbs = new[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
IEnumerable<int> result1 = nbs.Where(x => x > 5);
ParameterExpression parameter = Expression.Parameter(typeof(int), "x");
ConstantExpression constant = Expression.Constant(5);
BinaryExpression expressionBody = Expression.GreaterThan(parameter, constant);
Expression<Func<int, bool>> expression = Expression.Lambda<Func<int, bool>>(expressionBody, parameter);
IEnumerable<int> result2 = nbs.Where(expression.Compile());
But, how do I create a more complex lambda like this p=>p.FindAttribute("Gender")?.Value == "Female" in the same style as above?
public class Person
{
public bool POI { get; set; } = false;
public string Name { get; set; }
public List<Car> Cars { get; set; }
public List<Attribute> Attributes { get; set; }
public bool PersonOfInterest()
{
return POI;
}
public Attribute FindAttribute(string name)
{
return Attributes.FirstOrDefault(a => a.Name == name);
}
}
public class Attribute
{
public string Name { get; set; }
public string Value { get; set; }
public Attribute(string name, string value) { Name = name; Value = value; }
}
public class Car
{
public string Make { get; set; }
public int Horsepowers { get; set; }
public string Fuel { get; set; }
}
Person p1 = new Person();
p1.Name = "Thom";
p1.POI = true;
p1.Attributes = new List<Attribute>() {new Attribute("Length", "Tall"), new Attribute("Hair", "Long hair")};
p1.Cars = new List<Car>()
{
new Car(){Horsepowers = 100, Make = "Toyota", Fuel = "Diesel"},
new Car(){Horsepowers = 200, Make = "Fiat", Fuel = "Diesel"},
new Car(){Horsepowers = 300, Make = "Audi", Fuel = "Diesel"},
new Car(){Horsepowers = 150, Make = "Ferrari", Fuel = "Petrol"}
};
Person p2 = new Person();
p2.POI = false;
p2.Attributes = new List<Attribute>() { new Attribute("Nationality", "English"), new Attribute("Gender", "Female") };
p2.Name = "Sophie";
p2.Cars = new List<Car>()
{
new Car(){Horsepowers = 500, Make = "McLaren", Fuel = "Diesel"},
new Car(){Horsepowers = 200, Make = "Volvo", Fuel = "Diesel"},
new Car(){Horsepowers = 300, Make = "Audi", Fuel = "Diesel"},
new Car(){Horsepowers = 400, Make = "Ferrari", Fuel = "Diesel"}
};
IEnumerable<Person> res = persons.Where(p=>p.FindAttribute("Gender")?.Value == "Female");
Of course I could always create a new method on Person like:
public bool HasAttributeWithValue(string name, string value)
{
return FindAttribute(name)?.Value == value;
}
But it's still of interest to me if it's possible to construct the complex lambda dynamically!

This piece of code does the job.
ParameterExpression parameter = Expression.Parameter(typeof(Person), "p");
ConstantExpression my_null_object = Expression.Constant(null);
ConstantExpression gender = Expression.Constant("Gender");
MethodCallExpression methodcall = Expression.Call(parameter, typeof(Person).GetMethod("FindAttribute"), gender);
BinaryExpression is_null = Expression.Equal(methodcall, my_null_object);
ConstantExpression constant = Expression.Constant("Female");
MemberExpression member = Expression.Property(methodcall, typeof(Attribute).GetProperty("Value"));
BinaryExpression expressionBody = Expression.Equal(member, constant);
BinaryExpression cond = Expression.AndAlso(Expression.IsFalse(is_null), expressionBody);
Maybe clearer this way
ParameterExpression parameter = Expression.Parameter(typeof(Person), "p");
ConstantExpression my_null_object = Expression.Constant(null);
MethodCallExpression methodcall = Expression.Call(parameter, typeof(Person).GetMethod("FindAttribute"), Expression.Constant("Gender"));
BinaryExpression cond = Expression.AndAlso(
Expression.IsFalse(Expression.Equal(methodcall, my_null_object)),
Expression.Equal(
Expression.Property(methodcall, typeof(Attribute).GetProperty("Value")),
Expression.Constant("Female")
)
);

Null-conditional operator is a language feature. It can be converted to this code:
var attribute = p.FindAttribute("Gender");
return attribute == null ? false : attribute.Value == "Female";
To build an expression tree you can use Expression.Block:
var p = Expression.Parameter(typeof(Person), "p");
var findAttribute = Expression.Call(p,
typeof(Person).GetMethod(nameof(Person.FindAttribute)),
Expression.Constant("Gender"));
var attribute = Expression.Parameter(typeof(Attribute), "attribute");
var body = Expression.Block(
new[] {attribute}, // local variables
new Expression[]
{
Expression.Assign(attribute, findAttribute),
Expression.Condition(
Expression.Equal(attribute, Expression.Constant(null)),
Expression.Constant(false),
Expression.Equal(
Expression.PropertyOrField(attribute, "Value"),
Expression.Constant("Female")))
}
);
var lambda = Expression.Lambda<Func<Person, bool>>(body, p);

Related

PATCH in web API for Many to Many relationships using EF

I'm trying to remove a tag from a list of tags using a PATCH request. But while saving changes to the db context I get the following error:.
This the the PATCH code.
[HttpPatch("{id:int}/{field}", Name = "UpdateNote")]
[ProducesResponseType(StatusCodes.Status204NoContent)]
[ProducesResponseType(StatusCodes.Status404NotFound)]
public IActionResult UpdateNote(int id, string field, JsonPatchDocument<CreateNoteDTO> patchNoteDTO)
{
if (id == 0 || patchNoteDTO == null)
return BadRequest();
var note = _db.Notes.AsNoTracking().FirstOrDefault(u => u.ID == id);
if (note == null)
return NotFound();
CreateNoteDTO createNoteDTO = _mapper.Map<CreateNoteDTO>(note);
if (field.Equals("tags"))
{
var tags = _db.Tags.Where(u => u.Notes.Any(x => x.ID == note.ID)).AsNoTracking().ToList();
List<TagDTO> tagDTOs = new List<TagDTO>();
if (tags.Count > 0)
{
foreach (var tag in tags)
{
TagDTO tagDTO = _mapper.Map<TagDTO>(tag);
tagDTOs.Add(tagDTO);
}
}
createNoteDTO.Tags = tagDTOs;
}
patchNoteDTO.ApplyTo(createNoteDTO, ModelState);
if (!ModelState.IsValid)
return BadRequest(ModelState);
Note updateNote = _mapper.Map<Note>(createNoteDTO);
updateNote.ID = id;
updateNote.ChangedDate = DateTime.Now;
_db.Update(updateNote);
if (!field.ToLower().Equals("category"))
_db.Entry(updateNote).Property(u => u.FKCategory).IsModified = false;
_db.Entry(updateNote).Property(u => u.CreatedDate).IsModified = false;
_db.SaveChanges();
return NoContent();
}
My ApplicationDBContext looks like this:
public class ApplicationDbContext : DbContext
{
public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options) : base(options)
{
}
public DbSet<Note> Notes { get; set; }
public DbSet<Category> Categories { get; set; }
public DbSet<Tag> Tags { get; set; }
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
//Write Fluent API configurations here
modelBuilder.Entity<Note>()
.HasOne(e => e.Category)
.WithMany(e => e.Notes)
.HasForeignKey(e => e.FKCategory)
.OnDelete(DeleteBehavior.Cascade);
modelBuilder.Entity<Note>()
.HasMany(n => n.Tags)
.WithMany(t => t.Notes)
.UsingEntity(j => j
.ToTable("NoteTag")
.HasData
(
new { NotesID = 1, TagsTagID = 1 },
new { NotesID = 2, TagsTagID = 2 }
));
modelBuilder.Entity<Category>().HasData
(
new Category
{
CategoryID = 1,
CategoryName = "testCategory1",
CreatedDate = DateTime.Now
},
new Category
{
CategoryID = 2,
CategoryName = "testCategory2",
CreatedDate = DateTime.Now
}
);
modelBuilder.Entity<Tag>().HasData
(
new Tag
{
TagID = 1,
TagName = "testTag1",
CreatedDate = DateTime.Now
},
new Tag
{
TagID = 2,
TagName = "testTag2",
CreatedDate = DateTime.Now
}
);
modelBuilder.Entity<Note>().HasData
(
new Note
{
ID = 1,
Title = "testTitle1",
Description = "testDescription1",
FKCategory = 1,
Deleted = false,
CreatedDate = DateTime.Now,
ChangedDate = DateTime.Now,
},
new Note
{
ID = 2,
Title = "testTitle2",
Description = "testDescription2",
FKCategory = 2,
Deleted = false,
CreatedDate = DateTime.Now,
ChangedDate = DateTime.Now,
}
);
}
}
Any suggestions?
Thanks in advance.
Initially I tried without the following if condition:
CreateNoteDTO createNoteDTO = _mapper.Map<CreateNoteDTO>(note);
if (field.Equals("tags"))
{
var tags = _db.Tags.Where(u => u.Notes.Any(x => x.ID == note.ID)).AsNoTracking().ToList();
List<TagDTO> tagDTOs = new List<TagDTO>();
if (tags.Count > 0)
{
foreach (var tag in tags)
{
TagDTO tagDTO = _mapper.Map<TagDTO>(tag);
tagDTOs.Add(tagDTO);
}
}
createNoteDTO.Tags = tagDTOs;
}
But I got a different error:
I wanted to remove a tag form the following object using a PATCH request:
Note Object

how use memorycache in this method?

how can i add memorycache in this method ?
this is a section of my code that i want to set memory cache on it.
public IActionResult Index(int pageId = 1, string filter = "",
int startPrice = 0, int endPrice = 0, string getType = "", string orderByType = "date",
List<int> selectedGroups = null, List<int> selectedBrand = null, List<int> selectedTags = null
, List<int> selectedsize = null , string Discount = "")
{
ViewBag.selectedGroups = selectedGroups;
ViewBag.selectedTags = selectedTags;
ViewBag.selectedsize = selectedsize;
ViewBag.Discount = Discount;
ViewBag.getType = getType;
ViewBag.Groups = _productService.GetAllGroup();
ViewBag.Tags = _productService.GetTags().Where(c => c.ActiveRow).ToList();
ViewBag.size = _productService.GetSizes().ToList();
ViewBag.pageId = pageId;
return View(_productService.GetProducttype(pageId, filter, startPrice, endPrice, getType, orderByType, selectedGroups, selectedBrand, 24, selectedTags, selectedsize, Discount));
}
private readonly IMemoryCache _memoryCache;
public Constructor (IMemoryCache memoryCache)
{
_memoryCache = memoryCache;
}
public IActionResult Index(int pageId = 1, string filter = "",
int startPrice = 0, int endPrice = 0, string getType = "", string orderByType = "date",
List<int> selectedGroups = null, List<int> selectedBrand = null, List<int> selectedTags = null
, List<int> selectedsize = null , string Discount = "")
{
ViewBag.selectedGroups = selectedGroups;
ViewBag.selectedTags = selectedTags;
ViewBag.selectedsize = selectedsize;
ViewBag.Discount = Discount;
ViewBag.getType = getType;
var groups = new List<Group>();
if (_memoryCache.TryGetValue("groups", out groups)
{
ViewBag.Groups = groups;
}
else
{
groups = _productService.GetAllGroup();
_memoryCache.Set("groups", groups);
ViewBag.Groups = groups;
}
var tags = new List<Tag>();
if (_memoryCache.TryGetValue("tags", out tags)
{
ViewBag.Tags = tags;
}
else
{
tags = _productService.GetTags().Where(c => c.ActiveRow).ToList();
_memoryCache.Set("tags", tags);
ViewBag.Tags = tags;
}
var sizes = new List<Size>();
if (_memoryCache.TryGetValue("sizes", out sizes)
{
ViewBag.size = sizes;
}
else
{
sizes = _productService.GetSizes().ToList();
_memoryCache.Set("sizes", sizes);
ViewBag.size = sizes;
}
var pageId = null;
if (_memoryCache.TryGetValue("pageId", out pageId))
{
ViewBag.pageId = pageId;
}
else
{
_memoryCache.Set("pageId", pageId);
ViewBag.pageId = pageId;
}
return View(_productService.GetProducttype(pageId, filter, startPrice, endPrice, getType, orderByType, selectedGroups, selectedBrand, 24, selectedTags, selectedsize, Discount));
}

Read Data attributes or Custom Attributes in SQL server from string

I want in SQL prepared dynamic query based on the shortcode.
For Eg.
DECLARE #ShortCode VARCHAR(MAX)
SET #ShortCode = '[User data="Name" data="MobileNumber"]';
User = table name
Name = User table field
MobileNumber = User table field
Query output be like
SELECT [Name],[MobileNumber] FROM [dbo].[User]
SET #ShortCode = '[Country data="Name" ID="1"]';
Country = table name
Name = Country table field
ID = User table field
Query output be like
SELECT [Name] FROM [dbo].[Country] WHERE [ID] = 1
How to extract all data attributes values and how to get User in the []
This functionality is done in C#
Here My c# code
// Model class
public class ShortCodeResult
{
public Guid? ID { get; set; }
public string TableName { get; set; }
public bool IsValidShortCode { get; set; }
public string Message { get; set; }
public Dictionary<string,object> KeyValue { get; set; }
public ShortCodeResult() {
KeyValue = new Dictionary<string, object>();
ID = Guid.NewGuid();
}
}
//Regex Filter
public class RegexFilter
{
private string oPattern = #"(\w+)=[\""]([a-zA-Z0-9_.:\""]+)";
public ShortCodeResult GetShortCodeValues(string Code)
{
var oShortCodeModel = new ShortCodeResult();
var oRegex = new Regex(oPattern, RegexOptions.IgnoreCase);
var oTableNameRegex = Regex.Match(Code, #"\b[A-Za-z]+\b", RegexOptions.Singleline).Value;
var lstMatchCollection = oRegex.Matches(Code).Cast<Match>().Where(x=>x.Value.StartsWith("data")).ToList();
if (lstMatchCollection != null && lstMatchCollection.Count > 0)
{
for (int i = 0; i < lstMatchCollection.Count; i++)
{
var oSelected = new Regex("[^=]+$").Match(Convert.ToString(lstMatchCollection[i]));
if (oSelected != null)
{
oShortCodeModel.KeyValue.Add(i.ToString(), oSelected.Value.Trim('"'));
}
}
}
oShortCodeModel.TableName = oTableNameRegex;
return oShortCodeModel;
}
}
//HtmlHelper Extension
public static MvcHtmlString RenderShortCode(this HtmlHelper htmlHelper, string IdOrExprssion)
{
#region Get short code data
var oShortCode = ShortCodeHelper.GetShortCode(IdOrExprssion);
#endregion
var oMvcHtmlString = new MvcHtmlString(IdOrExprssion);
var oRegexFilter = new RegexFilter();
var shortCodeModel = oRegexFilter.GetShortCodeValues(oShortCode.Expression);
var ostringBuilder = new StringBuilder();
if (!string.IsNullOrEmpty(shortCodeModel.TableName))
{
ostringBuilder.AppendLine("SELECT ");
ostringBuilder.AppendLine((shortCodeModel.KeyValue.Count > 0 ? string.Join(",", shortCodeModel.KeyValue.Select(x => x.Value)) : "*"));
ostringBuilder.AppendLine(" FROM ");
ostringBuilder.AppendLine(oShortCode.TableName);
ostringBuilder.AppendLine(" WITH(NOLOCK) ");
if (oShortCode.FilterCode.Count() > 0)
{
ostringBuilder.AppendLine("WHERE ");
foreach (var filterCode in oShortCode.FilterCode)
{
ostringBuilder.AppendLine(filterCode.FilterColumnName);
ostringBuilder.AppendLine(filterCode.Operator);
ostringBuilder.AppendLine(filterCode.FilterColumnValue);
}
}
}
var oDyanamicData = DBHelper.GetDataTable(ostringBuilder.ToString(), System.Data.CommandType.Text, new List<SqlParameter>());
if (oDyanamicData != null)
{
if (oShortCode.IsHtmlRender)
{
for (int i = 0; i < oDyanamicData.Rows.Count; i++)
{
for (int j = 0; j < oDyanamicData.Columns.Count; j++)
{
string key = Convert.ToString(oDyanamicData.Columns[j]);
string value = Convert.ToString(oDyanamicData.Rows[i].ItemArray[j]);
if (oShortCode.DisplayCode.Count > 0)
{
var displayCode = oShortCode.DisplayCode.FirstOrDefault(x => x.DisplayColumnName == key);
if (displayCode != null && !string.IsNullOrEmpty(displayCode?.ReplaceKey))
{
oShortCode.DefinedHtml = oShortCode.DefinedHtml.Replace(displayCode.ReplaceKey, value);
}
}
}
}
return new MvcHtmlString(oShortCode.DefinedHtml);
}
else
{
string key = string.Empty, value = string.Empty;
#region For Json
List<JObject> dataList = new List<JObject>();
for (int i = 0; i < oDyanamicData.Rows.Count; i++)
{
JObject eachRowObj = new JObject();
for (int j = 0; j < oDyanamicData.Columns.Count; j++)
{
key = Convert.ToString(oDyanamicData.Columns[j]);
value = Convert.ToString(oDyanamicData.Rows[i].ItemArray[j]);
eachRowObj.Add(key, value);
}
dataList.Add(eachRowObj);
}
return new MvcHtmlString(Newtonsoft.Json.JsonConvert.SerializeObject(dataList));
#endregion
}
}
return oMvcHtmlString;
}
Can anyone help me solved above in SQL server or prepared query in store procedure

error not applied operand string to int null type

public ActionResult update( int? id)
{
BusDetailsModel model = new BusDetailsModel();
using (var ent = new OnlineReservation.AddData.OnlineReservationEntities1())
{
var db = ent.BusDetails.FirstOrDefault(x=>x.busId ==id);
model.BusId = db.busId;
model.Busname = db.busname;
model.Busowner = db.busowner;
model.Bustype = db.busType;
model.Buscapacity = db.busCapacity;
}
return View(model);
}

How to map collections in proper way

What is the best way for mapping collection of objects in NHibernate?
Now I am using bags, but maybe another approach can be more efficient?
Before wore Bag and ClassMapping, something very similar to this:
Bag(am => am.AlumnoMateriaId, map =>
{
map.Table("Calificacion");
map.Cascade(Cascade.None);
map.Key(k =>
{
k.Column("AlumnoId");
k.ForeignKey("FK_Calificacion_AlumnoMateria");
});
}, rel => rel.ManyToMany(p => p.Column("AlumnoId")));
Now Use the NHibernate.Mapping.Attributes, and a class would look like:
using NHMA = NHibernate.Mapping.Attributes;
[NHMA.Class(Table = " Calificacion ")]
public class Calificacion
{
[NHMA.Id(0, Name = "id", TypeType = typeof(Int32), Column = "Id", Access = "field")]
[NHMA.Generator(1, Class = "native")]
public Int32 id;
public virtual Int32 Id
{
get { return id; }
set { id = value; }
}
[NHMA.ManyToOne(2, Name = "calificacion", Access = "field", Column = "CalificacionID",
Class = "Calificacion", ClassType = typeof(Calificacion),
ForeignKey = "FK_Calificacion_Alumno", NotNull = false)]
private Calificacion calificaion;
public virtual Calificacion Calificaion
{
get { return calificaion; }
set { calificaion = value; }
}
[NHMA.Property(Name = "nombre", Access = "field", Column = "Nombre", Length = 50)]
private string nombre;
public virtual string Nombre
{
get { return nombre; }
set { nombre = value; }
}
}