Asp.Net Mvc delete columns from database table - c#

I am trying to delete all table data where username = current user name. But there is some error on lambda expression and conversion."Cannot convert source type to target type. Any help?
public JsonResult DeleteChatMessages(int id)
{
string toId = Session["SessionUserName"].ToString();
tblChat tblchats = _obj.tblChat.Where(p => p.ToId == toId);
_obj.tblChat.Remove(tblchats);
_obj.SaveChanges();
return this.Json(true, JsonRequestBehavior.AllowGet);
}

I am assuming you are expecting only one object to return from the Where filter.
Change your line as,because as per this . The Where clause returns an IEnumerable<TSource>. And you are assigning that to the non IEnumerable object.
tblChat tblchats = _obj.tblChat.FirstOrDefault(p => p.ToId == toId)
and you also might want to check for the Null, before removing it from the tblChat.
If you are expecting more than one object to match the filter and want to remove all of them then use #tmg approach.
_obj.tblChat.RemoveRange(_obj.tblChat.Where(p => p.ToId == toId).ToList());

Filter the "chats" you want.
var tblchats = _obj.tblChat.Where(p => p.ToId == toId).ToList();
After iterate throught them and remove.
foeach(chat in tblchats){
_obj.tblChat.Remove(chat);
}
_obj.SaveChanges();

Related

Strange Issue With GUID Search using C#

I'm trying to learn to use ABP with Blazor and MongoDB. I've got a set of objects in a database that I display as a list but I also want to be able to retrieve objects from the database by the object's GUID and this is where I'm running into problems.
This is the task I wrote to retrieve objects based on a filter from the database:
private async Task GetObjectAsync(string filter)
{
var result = await ObjectAppService.GetListAsync(
new GetObjectListDto
{
MaxResultCount = PageSize,
SkipCount = CurrentPage * PageSize,
Sorting = CurrentSorting,
Filter = filter
}
);
ObjectList = result.Items;
TotalCount = (int)result.TotalCount;
errorVal = TotalCount.ToString();
This is my GetListAsync() method where I retrieve objects from the database according to the filter string:
public async Task<PagedResultDto<ObjectDto>> GetListAsync(GetObjectListDto input)
{
if (input.Sorting.IsNullOrWhiteSpace())
{
input.Sorting = nameof(Object.Payload);
}
var objects = await _objectRepository.GetListAsync(
input.SkipCount,
input.MaxResultCount,
input.Sorting,
input.Filter
);
var totalCount = input.Filter == null
? await _objectRepository.CountAsync()
: await _objectRepository.CountAsync(
** SEARCH METHODS GO HERE **
return new PagedResultDto<ObjectDto>(
totalCount,
ObjectMapper.Map<List<Object>, List<ObjectDto>>(objects)
);
}
These are the search methods I've been trying:
object => object.Name.Contains(input.Filter));
object => object.Id.ToString().Contains(input.Filter));
object => object.Id.Equals(Guid.Parse(input.Filter)));
The first search method (search by name and return any DB results which contain it) works perfectly except for the fact I want to be able to search by GUID. The second search method would be ideal except it throws an exception when I use it:
(System.ArgumentException: Unsupported filter: {document}{_id}.ToString().Contains("70f35018-a504-89f1-51c0-3a04cb49cb97").).
The third search method definitely retrieves something from the database (I have verified) but it doesn't display this result on the page for some reason and I obviously have to enter a complete GUID to return the object (not ideal).
I'm sure this is possible and I'm doing something wrong here but I'm not sure what that is. Can anyone tell me the correct way to search by GUID here? I expected Id.ToString().Contains(Filter) to work.
UPDATE:
I've sort of solved this problem - I needed to look at the MongoObjectRepository.cs file:
public async Task<List<Object>> GetListAsync(
int skipCount,
int maxResultCount,
string sorting,
string filter = null)
{
var queryable = await GetMongoQueryableAsync();
return await queryable
.WhereIf<Object, IMongoQueryable<Object>>(
!filter.IsNullOrWhiteSpace(),
obj => obj.Id.Equals(filter)
)
.OrderBy(sorting)
.As<IMongoQueryable<Object>>()
.Skip(skipCount)
.Take(maxResultCount)
.ToListAsync();
}
For some reason, I was filtering based on the Payload property rather than Id.
I'm still confused, however, why obj => obj.Id.ToString().Contains((filter)) doesn't work - is this not allowed when retrieving items from a database? I've tried this on DateTimeOffset fields as well (e.g. obj => obj.InsertTimestamp.ToString().Contains((filter))) and get similar problems. When I try to add the .FirstOrDefault() to the end of the .WhereIf<Object, IMongoQueryable<Object>>() statement it invalidates the function (has to be chained with all the other methods - maybe that's the problem there?)

How to bind data to DTO attribute based on a condition?

I'm trying to bind data to a variable known as CurrentControlled that is defined in my DTO (Data transfer object), The issue is that i want to assign a string based on what data is returned from the database. In this case i have a table in my database known as RiskActions which has a column known as ActionCompleteDate, if the data inside ActionCompleteDate has date value in it than the string assigned to CurrentControlled should be 'Current', whereas if there is no date present inside ActionCompleteDate then the value for CurrentControlled should be Controlled.
I have tried assigning a condition to CurrentControlled but for some reason the compiler gives me an error.
var actions = dataContext.RiskInstances.Where(riskInstancePredicate.Compile());
actions = actions
.OrderBy(a => a.RiskInstanceID2)
.ThenBy(a=> a.Issue.Question);
List<RiskDTO> results = actions
.Select(ra => new RiskDTO
{
CurrentControlled = if(ra.RiskActions.Where(m => m.ActionCompleteDate == null)) {
TerminologyFactor.Parse("{Current}",TerminologyFactor.RMMonitor)
}
else {
TerminologyFactor.Parse("{Controlled}",TerminologyFactor.RMMonitor)
}
})
You need to use the conditional operator. Also, this is a guess because I don't know your data structure here, but you likely need to use Any instead of Where as it returns a boolean you can use as the condition:
List<RiskDTO> results = actions
.Select(ra => new RiskDTO
{
CurrentControlled = ra.RiskActions.Any(m => m.ActionCompleteDate == null))
? TerminologyFactor.Parse("{Current}",TerminologyFactor.RMMonitor)
: TerminologyFactor.Parse("{Controlled}",TerminologyFactor.RMMonitor)
}

NHibernate: How to load only specific properties in a list of entities (instead of full object)?

I have been using NHibernate in my project and it is working very good until the time.
Now I am facing one problem and don't know how to solve it.
Problem is I want to fetch only x columns from table instead of all and then bind this to original entity with fetched columns assigned values where for others should show null.
e.g. I have table Employee as
FieldName DataType
ID int
FName nvarchar(500)
LName nvarchar(500)
Resume nvarchar(max)
From above I want to fetch only Id, FName, LName only and bind it to Employee entity and then we would like to load Resume by making separate database call using NHibernate.
I tried
var list = session
.CreateCriteria(typeof (Employee))
.SetProjection(Projections
.ProjectionList()
.Add(Projections.Property("Id"))
.Add(Projections.Property("FName"))
.Add(Projections.Property("LName")))
.List();
but above code returns restricted column data but in form of array of object.
I wanted this to get bind to entity instead of object array.
So, please share your thoughts on this
You need to set the ResultTransformer and call ToList() with the type, otherwise NHibernate didn't know what to do with the projections. And you need also to specifiy the target property names in your Employee type.
Your query can look simething like this:
var list = session
.CreateCriteria(typeof (Employee))
.SetProjection(Projections
.ProjectionList()
.Add(Projections.Property("Id"), "Id")
.Add(Projections.Property("FName"), "FirstName")
.Add(Projections.Property("LName"), "LastName"))
.SetResultTransformer(Transformers.AliasToBean<Employee>())
.List<Employee>();
Please note: "Id", "FirstName" and "LastName" must be properties in the Employee type.
Answer from #Rabban explains it well; +1 to him. I am just putting it differently.
As you observed, SetProjection will return array of objects. To convert objects to entities, you need to call SetResultTransformer(Transformers.AliasToBean<Entity>(). The code sample is already given in other answer; I will not repeat it.
Problem with your current code is that, you need to type in column names as string. I generally avoid this approach. I prefer to use strongly typed version of same with IQueryOver as below:
public IList<TEntity> GetList<TEntity>(ProjectionList columnList, Junction where, int top) where TEntity : BaseEntity
{
IQueryOver<TEntity> query = null;
if((columnList != null) && (where != null))
{
query = session.QueryOver<TEntity>()
.Select(columnList)
.TransformUsing(Transformers.AliasToBean<TEntity>())
.Where(where);
}
else if((columnList != null) && (where == null))
{
query = session.QueryOver<TEntity>()
.Select(columnList)
.TransformUsing(Transformers.AliasToBean<TEntity>());
}
else if((columnList == null) && (where != null))
{
query = session.QueryOver<TEntity>()
.Where(where);
}
else
{
query = session.QueryOver<TEntity>();
}
IList<TEntity> result = query.Take(top).List();
return result;
}
You can pass strongly typed list of columns to this method as below:
ProjectionList columnList = Projections.ProjectionList();
columnList.Add(Projections.Property<Employee>(x => x.Id));
...
...

Get the first item property with lambda expression

In C#, I'm going to use lambda expression, I have such a code
var item = dbContext.Products.ToList();
How can i get a property of Product table.
try this
var item = dbContext.Products.FirstOrDefault().Name;
With Lamba expression normally you can access and read information from "list" or in this case, IQueryable objects.
With your code you can access to objects with something like this:
var item = dbContext.Products.FirstOrDefault();
// item may be null if products table is empty
if (item != null)
{
// now you can access at object properties (example)
var data = item.PropertyData;
}
Your question may open others way that including reflection for exploring object without well known class definition...
If you want to get the property for each product with lambda expression, then you should make a lambda expression like x => x.Prop when you do your query
if (dbContext.Products != null){
var list = dbContext.Products.ToList();
var query = list.Select(x => x.Prop //your property will appear here...
}

RavenDB - Index sorting for Alphanumeric property

I am trying to index an alphanumeric property that should be sorted as follows:
WS1-1-14-1
WS1-1-15-1
WS1-1-15-2
WS1-1-15-3
I created an index that removes the non numeric characters of the property and set the SortOptions to Int so i can order then as above.
Here is my index definition:
Map = fixtures => from f in fixtures
select new
{
FixtureNumber = f.FixtureNumber.Replace("-", "").Replace("WS", ""),
};
Sort(x => x.FixtureNumber, SortOptions.Int);
The sorting works fine when i do and OrderBy on the Index:
session.Query<Fixture, Fixtures_All>.OrderBy(x => x.FixtureNumber).ToList()
But my problem is that when i do a dynamic Query on my Fixture document its like the query is still using my index:
session.Query<Fixture>.FirstOrDefault(x => x.FixtureNumber == "WS1-1-1");
Returns no results, which i would expect it would as im not querying my index. But the following does work, which i find strange:
var fixNo = "WS1-15-1".Replace("-", "").Replace("WS", "");
session.Query<Fixture>.FirstOrDefault(x => x.FixtureNumber == fixNo);
Why is my index affecting this dynamic index query ?
Also is there a better way to index my property without resorting to string replace to make it an integer ?
Thanks
Note:
If i just use the default string comparer on the SortOptions the results get sorted like so:
WS1-1-15-1
WS1-1-15-10
WS1-1-15-2
WS1-1-15-3
...
Raven will always look for an index on the given type and for an indexed property (by name) on that type when doing an dynamic index. If it can't find one, it will auto-generate one first.
When you issue the following query:
session.Query<Fixture>.FirstOrDefault(x => x.FixtureNumber == "WS1-1-1");
Raven will find that there is indeed an index on Fixture on the property FixtureNumber defined by the Fixtures_All index. The problem here is that the stored FixtureNumber inside the index is altered (stripped dash and letters) so Raven will use that to map your query (it doesn't know that it's been altered).
If you look at the index in the Raven studio you can select "Index Entries" to show what the actual index looks like on disk:
This is why you don't get any results when issue the query.
If you want to use an altered property in the index you can do the following:
Map = fixtures => from f in fixtures
select new
{
ShortenFixtureNumber = f.FixtureNumber.Replace("-", "").Replace("WS", ""),
FixtureNumber = f.FixtureNumber
};
Sort("ShortenFixtureNumber", SortOptions.Int);
Then you can create something I like to call a "Query Model" (not sure if that's the right name):
public class FixtureQueryModel
{
public string FixtureNumber { get; set; }
public int ShortenFixtureNumber { get; set; }
}
With this, I can query both by the index using the "Query model" and also query directly on the type:
var fixture = session.Query<FixtureQueryModel, Fixtures_All>()
.Where(x => x.FixtureNumber.StartsWith("WS1"))
.OrderBy(x => x.ShortenFixtureNumber)
.As<Fixture>()
.ToList();
var fixture2 = session.Query<Fixture>()
.FirstOrDefault(x => x.FixtureNumber == "WS1-1-14-1");
However, this might seem rather complicated and in your case I think the default string sort comparer would work directly on an un-altered FixtureNumber, but hopefully this post provides some help into what's going on with indexes.

Categories

Resources