asp.net core delete everything with certain number - asp.net-core-2.0

I want to delete all vragen(questions in english) with the classID for example number 5. It is possible to give a vraagID and a classID and the server deletes the question if it matches. But I want to delete all matching questions with only one request. Is this possible?
namespace AspIdentityServer.data
{
public class Vraag :Conversatie
{
public int VraagID { get; set; }
public int classID { get; set; }
public string Titel { get; set; }
public ICollection<Antwoord> Antwoord { get; set; }
public Vak Vak { get; set; }
}
}
--
// DELETE: api/Vraags/1/alles/5
[AllowAnonymous]
[HttpDelete("{id}/alles/{vakID}")]
public async Task<IActionResult> DeleteAlleVragen([FromRoute] int id, int vakID) {
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
var vraag = await _context.Vraag.SingleOrDefaultAsync(m => m.VraagID == id);
if (vraag.classID == vakID)
{
_context.Vraag.Remove(vraag);
await _context.SaveChangesAsync();
}
return Ok(vraag);
}

You can always use the ExecuteSqlCommandAsync to execute your custom SQL queries. So write a single delete statements with appropriate where clause which will handle many rows as needed.
Here is a quick example
object[] paramsArray =
{
new SqlParameter
{
ParameterName = "#vraagId",
SqlDbType = SqlDbType.Int,
Value = id
},
new SqlParameter
{
ParameterName = "#classId",
SqlDbType = SqlDbType.Int,
Value = vakID
}
};
const string q = "DELETE FROM VraagWHERE VraagID=#vraagId and ClassId=#classId";
await _context.Database.ExecuteSqlCommandAsync(q, paramsArray);
Update the SQL statemenets and parameters as needed.

Related

How can i execute filter from our JSON filter JSON?

I have a vue3 datagrid and I want to fill the data in this grid with filter by API. At the same time, I want to send the filter fields in the grid to the API as JSON and execute them according to this filter on the API side. How can I do this with AutoQuery?
[Route("/GetConnectors", "POST")]
public class GetConnectors : QueryDb<Connector>
{
public string Id { get; set; }
public string PageParameterJson { get; set; }
}
public class Connector
{
[PrimaryKey]
[AutoIncrement]
public long PKey { get; set; }
public string Id { get; set; }
public string Name { get; set; }
}
public class PageParameters
{
public string Field { get; set; }
public string Operand { get; set; }
public string Value { get; set; }
public string Type { get; set; }
}
It's an example PageParameter JSON;
[
{
"Field":"Name",
"Operand":"cn"//Contains
"Value":"test",
"Type":"string"
},
{
"Field":"Id",
"Operand":"eq"//Equal
"Value":"2",
"Type":"string"
}
]
public async Task<object> Any(GetConnectors query)
{
using var db = AutoQuery.GetDb(query, base.Request);
var filters = query.PageParameters.FromJson<List<PageParameter>>();
//How can I execute query with for CreateQuery?
var q = AutoQuery.CreateQuery(query, Request, db);
var sql = q.PointToSqlString();
return await AutoQuery.ExecuteAsync(query, q, base.Request, dbConnection);
}
Best Regards
i can't execute dynamic filters from server-side datagrid
The AutoQuery.CreateQuery returns OrmLite's Typed SqlExpression which has a number of filtering options inc .Where(), .And(), .Or(), etc.
So you should be able to populate it with something like:
foreach (var filter in filters)
{
var type = filter.Type switch
{
"string" => typeof(string),
_ => throw new NotSupportedException($"Type {filterType}")
};
var value = filter.Value.ConvertTo(type);
if (filter.Operand == "eq")
{
q.And(filter.Field + " = {0}", value)
}
else if (filter.Operand == "cn")
{
q.And(filter.Field + " LIKE {0}", $"%{value}%")
}
else throw new NotSupportedException(filter.Operand);
}
Note: I've rewritten API to be async as you should never block on async methods.

In Orchard how do I create a query that includes an associated Part?

I'm working in a new module for an orchard project. We've build a Company Part which is associated with an Address Part. What I'm eventually trying to get to is allowing users to enter various search criteria via the ui (non-admin interface), perform a search against all companies and return any matching results.
Where I'm struggling is how to build the query which allows me to include info from the associated address. So far I've only been able to successfully return results based on the CompanyPartRecord as opposed to the CompanyPart. The CompanyPartRecord obviously only contains the Address_Id of the associated AddressPart.
In essence I'm trying to get to something like this which will return an enumerable or list of companies which match the entered search criteria. There are more search options beyond zip so I'm looking for an extensible solution.
var query = _companyRepository.Table.AsQueryable();
if (!string.IsNullOrEmpty(Zip))
query = query.Where(c => c.Address.Zip == Zip);
var queryResult = query.ToList();
I've tried using both an IRepository (shown above) and with IContentManager such as the following:
var query = _contentManager.Query<CompanyPart, CompanyPartRecord>();
//var query = _contentManager.Query<CompanyPart>();
if (!string.IsNullOrEmpty(Zip))
query = query.Where(c => c.Address.Zip == Zip);
var queryResult = query.ToList();
Here's the actual Company and Address (Parts and Records):
public class CompanyPartRecord : ContentPartRecord
{
public virtual string Name { get; set; }
public virtual string Description { get; set; }
public virtual int Address_Id { get; set; }
public virtual string Phone { get; set; }
public virtual string OtherInformation { get; set; }
public virtual string Website { get; set; }
public virtual bool Inactive { get; set; }
// Keywords - Taxonomy
// Logo - associated part
// HasMissingData - derived
// NumberOfEmployees - associated part
}
public class CompanyPart : ContentPart<CompanyPartRecord>, ITitleAspect
{
internal readonly LazyField<AddressPart> AddressField = new LazyField<AddressPart>();
public string Name
{
get { return Record.Name; }
set { Record.Name = value; }
}
public string Description
{
get { return Record.Description; }
set { Record.Description = value; }
}
public AddressPart Address
{
get { return AddressField.Value; }
set { AddressField.Value = value; }
}
public string Phone
{
get { return Record.Phone; }
set { Record.Phone = value; }
}
public string OtherInformation
{
get { return Record.OtherInformation; }
set { Record.OtherInformation = value; }
}
public string Website
{
get { return Record.Website; }
set { Record.Website = value; }
}
public bool Inactive
{
get { return Record.Inactive; }
set { Record.Inactive = value; }
}
public string Title
{
get { return Name; }
}
}
public class AddressPartRecord : ContentPartRecord
{
public virtual string Street { get; set; }
public virtual string Street2 { get; set; }
public virtual string City { get; set; }
public virtual string CountyName { get; set; }
public virtual NationRecord State { get; set; }
public virtual string Zip { get; set; }
}
public class AddressPart : ContentPart<AddressPartRecord>
{
public string Street
{
get { return Record.Street; }
set { Record.Street = value; }
}
public string Street2
{
get { return Record.Street2; }
set { Record.Street2 = value; }
}
public string City
{
get { return Record.City; }
set { Record.City = value; }
}
public string CountyName
{
get { return Record.CountyName; }
set { Record.CountyName = value; }
}
public NationRecord State
{
get { return Record.State; }
set { Record.State = value; }
}
public string Zip
{
get { return Record.Zip; }
set { Record.Zip = value; }
}
}
I assume that you have a Content Type that contains both Parts (ie. named Company), if that is the case this should work:
var query = _contentManager.Query("Company").Where<AddressPartRecord>(x => x.Street == "query street");
var list = query.ToList();
The list contains the ContentItems filtered by street. Using .As() and .As() over the items of the list you get access to each part.

C# 4.0 Entity Framework ExecuteStoreQuery:There is already an open DataReader

I use ExecuteStoreQuery and make an IEnumerable<> list. When I get this list with foreach and use some linq query in this area it give a this error :
There is already an open DataReader associated with this Connection which must be closed first.
What must I do for this ?
My code looks like that :
//IEnumerable function
public IEnumerable<NewTable> YirmiAjansTweetList()
{
string nativeSQLQuery = "Select t1.id,t1.baslik,t1.url,t1.gtarih,t3.ck,t3.cs,t2.token,t2.tokensecret from yirmiajanstweets t1 join uyeler t2 ON(t1.uid=t2.u_id) join uygulamalar t3 ON(t2.uyid=t3.u_id) where t1.gtarih is not null and t1.durum=0 and t1.gtarih<Now();";
IEnumerable<NewTable> newList = db.ExecuteStoreQuery<NewTable>(nativeSQLQuery, System.Data.Objects.MergeOption.NoTracking);
if (newList != null)
{
return newList;
}
else
{
return null;
}
}
public class NewTable
{
public int id { get; set; }
public string baslik { get; set; }
public string url { get; set; }
public DateTime gtarih { get; set; }
public string ck { get; set; }
public string cs { get; set; }
public string token { get; set; }
public string tokensecret { get; set; }
}
//look for a record function
public yirmiajanstweets YirmiAjansKayitBak(int _id)
{
yirmiajanstweets ya = db.yirmiajanstweets.FirstOrDefault(f => f.id == _id);
if (ya != null)
{
return ya;
}
else
{
return null;
}
}
//i get this list like that with foreach
IEnumerable<dynamic> ya = yaBLL.YirmiAjansTweetList().AsEnumerable();
if (ya != null)
{
foreach (var item in ya)
{
//when read this line give error
var myRecord = YirmiAjansKayitBak(item.id);
}
}
else
{
Response.Write("Not found !");
}
Try to add MultipleActiveResultSets=true to your connection string.
Try to load the query result into a list before you iterate over the collection:
IEnumerable<dynamic> ya = yaBLL.YirmiAjansTweetList().ToList();

Should I give up on Integer Ids for RavenDB?

Update: Here's a gist that more fully demonstrates the issue https://gist.github.com/pauldambra/5051550
Ah, more update... If I make the Id property on the Mailing class a string then it all works. Should I just give up on integer ids?
I have 2 models
public class Mailing
{
public int Id { get; set; }
public string Sender { get; set; }
public string Subject { get; set; }
public DateTime Created { get; set; }
}
public class Recipient
{
public Recipient()
{
Status = RecipientStatus.Pending;
}
public RecipientStatus Status { get; set; }
public int MailingId { get; set; }
}
On my home page I want to grab the last 10 mailings. With a count of their recipients (eventually with a count of different status recipients but...)
I have made the following index
public class MailingWithRecipientCount : AbstractMultiMapIndexCreationTask<MailingWithRecipientCount.Result>
{
public class Result
{
public int MailingId { get; set; }
public string MailingSubject { get; set; }
public string MailingSender { get; set; }
public int RecipientCount { get; set; }
}
public MailingWithRecipientCount()
{
AddMap<Mailing>(mailings => from mailing in mailings
select new
{
MailingId = mailing.Id,
MailingSender = mailing.Sender,
MailingSubject = mailing.Subject,
RecipientCount = 0
});
AddMap<Recipient>(recipients => from recipient in recipients
select new
{
recipient.MailingId,
MailingSender = (string) null,
MailingSubject = (string)null,
RecipientCount = 1
});
Reduce = results => from result in results
group result by result.MailingId
into g
select new
{
MailingId = g.Key,
MailingSender = g.Select(m => m.MailingSender)
.FirstOrDefault(m => m != null),
MailingSubject = g.Select(m => m.MailingSubject)
.FirstOrDefault(m => m != null),
RecipientCount = g.Sum(r => r.RecipientCount)
};
}
}
I query using
public ActionResult Index()
{
return View(RavenSession
.Query<RavenIndexes.MailingWithRecipientCount.Result, RavenIndexes.MailingWithRecipientCount>()
.OrderByDescending(m => m.MailingId)
.Take(10)
.ToList());
}
And I get:
System.FormatException: System.FormatException : Input string was not
in a correct format. at System.Number.StringToNumber(String str,
NumberStyles options, NumberBuffer& number, NumberFormatInfo info,
Boolean parseDecimal)
Any help appreciated
Yes, integer ids are a pain. This is mainly because Raven always stores a full string document key, and you have to think about when you are using the key or your own id and translate appropriately. When reducing, you also need to align the int and string data types.
The minimum to get your test to pass is:
// in the "mailings" map
MailingId = mailing.Id.ToString().Split('/')[1],
// in the reduce
MailingId = g.Key.ToString(),
However - you could make your index a whole lot smaller and perform better by taking the sender and subject strings out of it. You can just put them in with a transform.
Here is a simplified complete index that does the same thing.
public class MailingWithRecipientCount : AbstractIndexCreationTask<Recipient, MailingWithRecipientCount.Result>
{
public class Result
{
public int MailingId { get; set; }
public string MailingSubject { get; set; }
public string MailingSender { get; set; }
public int RecipientCount { get; set; }
}
public MailingWithRecipientCount()
{
Map = recipients => from recipient in recipients
select new
{
recipient.MailingId,
RecipientCount = 1
};
Reduce = results => from result in results
group result by result.MailingId
into g
select new
{
MailingId = g.Key,
RecipientCount = g.Sum(r => r.RecipientCount)
};
TransformResults = (database, results) =>
from result in results
let mailing = database.Load<Mailing>("mailings/" + result.MailingId)
select new
{
result.MailingId,
MailingSubject = mailing.Subject,
MailingSender = mailing.Sender,
result.RecipientCount
};
}
}
As an aside, did you know about the RavenDB.Tests.Helpers package? It provides a simple base class RavenTestBase that you can inherit from that does most all of the legwork for you.
using (var store = NewDocumentStore())
{
// now you have an initialized, in-memory, embedded document store.
}
Also - you probably shouldn't scan the assembly for indexes in a unit test. You might introduce indexes that weren't part of what you were testing. The better route is to create the index indvidually, like this:
documentStore.ExecuteIndex(new MailingWithRecipientCount());

ValueInjecter question

After working with AutoMapper I came across ValueInjecter on this site. I am trying it out but I am stuck on what is probably a very simple scenario.
But before I dig into the code sample, does anyone know if ValueInjecter works in a Medium-Trust web environment? (Like Godaddy?)
Ok, onto the code! I have the following models:
public class NameComponent
{
public string First { get; set; }
public string Last { get; set; }
public string MiddleInitial { get; set; }
}
public class Person
{
public NameComponent Name { get; set; }
}
that I want to map to the following DTO:
public class PersonDTO : BaseDTO
{
private string _firstName;
public string FirstName
{
get { return _firstName; }
set { NotifyPropertyChanged(() => FirstName, ref _firstName, value); }
}
private string _middleInitial;
public string MiddleInitial
{
get { return _middleInitial; }
set { NotifyPropertyChanged(() => MiddleInitial, ref _middleInitial, value); }
}
private string _lastName;
public string LastName
{
get { return _lastName; }
set { NotifyPropertyChanged(() => LastName, ref _lastName, value); }
}
}
So when I want to Map from Model to DTO I need a Model.Name.First -> DTO.FirstName
and when going from DTO to Model I need FirstName -> Name.First. From my understanding this is not a simple Flatten/UnFlatten, because the words also reverse themselves, ie: FirstName <--> Name.First. So First and Last names could use the same kind of rule, but what about MiddleInitial? Model.Name.MiddleInitial -> DTO.MiddleInitial.
I see there are some plugins, but none of them seem to do what I would want. Has anyone else come across this scenario?
the basic idea is that I match the Name with the FirstName, I take this as a pivot point, and in the method that usually sets the value to just one (FirstName) property I set it to 3 properties - that's for the FromNameComp
in the ToNameComp i match the same properties but I take the value from 3 and create one and set it
public class SimpleTest
{
[Test]
public void Testit()
{
var p = new Person { Name = new NameComponent { First = "first", Last = "last", MiddleInitial = "midd" } };
var dto = new PersonDTO();
dto.InjectFrom<FromNameComp>(p);
Assert.AreEqual(p.Name.First, dto.FirstName);
Assert.AreEqual(p.Name.Last, dto.LastName);
Assert.AreEqual(p.Name.MiddleInitial, dto.MiddleInitial);
var pp = new Person();
pp.InjectFrom<ToNameComponent>(dto);
Assert.AreEqual(dto.LastName, pp.Name.Last);
Assert.AreEqual(dto.FirstName, pp.Name.First);
Assert.AreEqual(dto.MiddleInitial, pp.Name.MiddleInitial);
}
public class FromNameComp : ConventionInjection
{
protected override bool Match(ConventionInfo c)
{
return c.SourceProp.Name == "Name" && c.SourceProp.Type == typeof(NameComponent)
&& c.TargetProp.Name == "FirstName"
&& c.SourceProp.Value != null;
}
protected override object SetValue(ConventionInfo c)
{
dynamic d = c.Target.Value;
var nc = (NameComponent)c.SourceProp.Value;
//d.FirstName = nc.First; return nc.First does this
d.LastName = nc.Last;
d.MiddleInitial = nc.MiddleInitial;
return nc.First;
}
}
public class ToNameComponent : ConventionInjection
{
protected override bool Match(ConventionInfo c)
{
return c.TargetProp.Name == "Name" && c.TargetProp.Type == typeof(NameComponent)
&& c.SourceProp.Name == "FirstName";
}
protected override object SetValue(ConventionInfo c)
{
dynamic d = c.Source.Value;
var nc = new NameComponent { First = d.FirstName, Last = d.LastName, MiddleInitial = d.MiddleInitial };
return nc;
}
}
public class NameComponent
{
public string First { get; set; }
public string Last { get; set; }
public string MiddleInitial { get; set; }
}
public class Person
{
public NameComponent Name { get; set; }
}
public class PersonDTO
{
public string FirstName { get; set; }
public string MiddleInitial { get; set; }
public string LastName { get; set; }
}
}
But before I dig into the code sample,
does anyone know if ValueInjecter
works in a Medium-Trust web
environment? (Like Godaddy?)
it doesn't use reflection.emit so it should work

Resources