Return a list of elements that are NOT in two previous lists - sql

I have 2 lists of IDs and I need to return a list with the products that aren't in any of those lists:
public IEnumerable<Produto> GetProdutosIdNotInFamily(Guid produtoId)
{
var produtosPai = GetListaPaisId(produtoId);
var produtosFilho = GetListaFilhosId(produtoId);
var prod = _dbContext.Produtos
.Where(u => !produtosPai.Any(p => p.ProdutoFilhoId == u.Id)
&& !produtosFilho.Any(p => p.ProdutoFilhoId == u.Id));
return prod;
}

You can do this in two ways -- One using Contains and other using Any like you provided in your snippet in the post.
Using Contains Method
If you want to use Contains() method, you may be pulling out all the product Ids into a collection and apply LINQ on top of it and get the list that is not part of both your reference lists. Sample code is as shown below
// This is the sample model I am dealing with
public class Dummy
{
public int Id { get; set; }
public string Name { get; set; }
}
// Assuming the below call returns list of 'Dummy' objects
var products = _dbContext.Produtos;
// list1 & list2 are populated in your case already through the method calls
var exclusionList1 = list1.Select(x => x.Id).ToList<int>();
var exclusionList2 = list2.Select(x => x.Id).ToList<int>();
var myList = products.Where(x => !exclusionList1.Contains(x.Id) && !exclusionList1.Contains(x.Id)).ToList();
Contains is an instance method and takes an object as a parameter and the time complexity depends on the collection you're using this on.
Using Any
Just like Where, Any is an extension method. It takes a delegate as a parameter which gives you greater flexibility and control with respect to what you would want to do.
Applying Any to your scenario is as shown below:
var products = _dbContext.Produtos;
var exclusionList1 = GetListaPaisId(produtoId);
var exclusionList2 = GetListaFilhosId(produtoId);
var prod = _dbContext.Produtos.Where(x => !exclusionList1.Any(z => x.Id == z.Id) &&
!exclusionList2.Any(z => x.Id == z.Id)).ToList();
You can choose your approach based on the context under which you are performing this operation.

Related

replace a returned property with another property from a different model linking by Id

Hi I'm not quite sure how to do this.
I have this .NetCore EntityFrame controller that gets a list of characters.
It works when I simply get the list of characters by doing this:
return await _context.Character.ToListAsync();
This returns the name, class, race, age, armorPoints, hitPoints, and spiritAnimalId for each character in the database.
But now, instead of simply returning just the spiritAnimalId, I want to return the actual name of the animal.
So I started writing some code, but quickly lost the ability to figure out how to return the name of the spirit animal.
Here is what I have:
// GET: api/Characters
[HttpGet]
public async Task<ActionResult<IEnumerable<Character>>> GetCharacters()
{
var characters= await _context.Character.ToListAsync();
foreach(Character c in characters)
{
var a = _context.SpiritAnimal.FindAsync(c.spiritAnimalId);
var name = a.Result.Name;
}
return charcters;
}
So I'm lost as to how to return the list of projects and replace the spiritAnimalId with it's name.
NEW CODE:
// GET: api/Characters
[HttpGet]
public async Task<ActionResult<List<Character>>> GetCharacters()
{
var characters = await _context.Character
.Select(x => new
{
x.Id,
x.Name,
x.Race,
x.Class,
x.Age,
SpiritAnimalName = x.SpiritAnimalName.Name
})
.ToListAsync();
return characters;
}
NEW ERROR:
Cannot implicitly convert type 'System.Collections.Generic.List<<anonymous type
to 'Microsoft.AspNetCore.Mvc.ActionResult<System.Collections.Generic.List
Thanks!
If you don't already, you should have a navigation property on your Character class like:
public SpiritAnimal SpiritAnimal { get; set; }
Then, when you make your query, you should include this relationship, so it's joined in the same query:
var characters = await _context.Character.Include(x => x.SpiritAnimal).ToListAsync();
As you're iterating over the characters, you can simply access: character.SpiritAnimal.Name. If you're wanting to only return the name from the query, you'll need to use Select to project into another class or an anonymous object:
var characters = await _context.Character
.Select(x => new
{
CharacterName = x.Name,
SpiritAnimalName = x.SpiritAnimal.Name
}
.ToListAsync();
When the Select expression utilizes a property on a related entity, you don't need to explicitly load it; EF is smart enough to realize it needs to do a join to satisfy the return.

I want to select different packages on the basis of states, how to get value

public ActionResult Rajasthan()
{
//List<PackageGallery> all = new List<PackageGallery>();
using (travelAndTourismEntities objentity = new travelAndTourismEntities())
{
List<PackageGallery> all = (from p in objentity.PackageGalleries where p.ParentCategory == "Rajasthan" orderby p.Imageid select p).ToList();
// all = objentity.PackageGalleries.ToList();
return View(all);
}
}
I am writing this query but this is specific to rajasthan only how to make it generalize
You can create a parameter to your action method where you accept the state name you want to use in your filter.
public ActionResult PackageGalleries(string id)
{
var all = new List<PackageGallery>();
using (var db = new travelAndTourismEntities())
{
all = db.PackageGalleries
.Where(s=>s.ParentCategory==id)
.OrderBy(x=>x.ImageId).ToList();
}
return View(all);
}
And you can call it like yourSiteName/yourControllerName/PackageGalleries/rajasthan or yourSiteName/yourControllerName/PackageGalleries/kerala
The last part of the url will be mapped to the id parameter of the action method.

breeze.js not honoring the "noTracking" option when end point returns multiple result sets

Consider this breze query:
return EntityQuery.from('myAPI')
.noTracking(true)
.using(manager).execute()
.then(querySucceeded)
.fail(queryFailed);
My API is defined like this:
[HttpGet]
public object myAPI()
{
// var userId = get the users id from auth ticket
var userPref = _contextProvider.Context.UserPreferences.Where(u => u.userId == userId);
var userOptions = _contextProvider.Context.UserOptions.Where(u => u.userId == userId);
return new
{
userPref,
userOptions
};
}
I know I can get access to the raw data, which is great. But in addition to this, the entities are created in the entity manager, which I would prefer they not be. This works fine for apis that return IQueryable. Is there a different syntax for noTracking for web apis that returns multiple result sets?
thanks
I can't reproduce the error you describe. I have a similar DocCode test that passes which references Breeze v1.5.3.
Here is the pertinent NorthwindController method:
[HttpGet]
public object Lookups()
{
var regions = _repository.Regions;
var territories = _repository.Territories;
var categories = _repository.Categories;
var lookups = new { regions, territories, categories };
return lookups;
}
And here's the passing QUnit test:
asyncTest('object query (e.g., lookups) w/ "no tracking" does not add to cache', function () {
expect(2);
var em = newNorthwindEm();
EntityQuery.from('Lookups')
.noTracking(true)
.using(em).execute()
.then(success).fail(handleFail).fin(start);
function success(data) {
var lookups = data.results[0];
var hasLookups = lookups &&
lookups.categories && lookups.regions && lookups.territories;
ok(hasLookups, 'Expected a lookups object w/ categories, regions and territories');
var cached = em.getEntities();
var len = cached.length;
equal(0, len, 'Expected ZERO cached entities of any kind and got ' + len);
}
});
If I comment out the noTracking(true) clause, the test fails and tells me that there are 65 entities in cache ... as predicted.
What am I missing?

Optimization of foreach statement, create new mapped Viewmodel list

Can someone please have a look at my code, I think there must be a way to optimize the foreach piece of code?
I have a database with Artists, each artist has multiple songTitles (called Titles), and each Title can have multiple Meanings.
Artist [1..*] Title [1..*] Meaning [0..*]
I want to find the count of Meanings, per Title, for an Artist, and return it as a new ViewModel List.
public class TitleVM
{
public int TitleID { get; set; }
public int MeaningCount { get; set; }
}
public List<TitleVM> GetTitlesByArtistID(int artistID)
{
//find the artist by ID
var titles = context.Titles.Where(x => x.ArtistID == artistID);
//create new VMList to be returned
var titleVMList = new List<TitleVM>();
//loop through each title,
foreach (var item in titles)
{
//find the number of meanings,
var count = 0;
if (item.Meanings != null && item.Meanings.Count > 0)
{
count = item.Meanings.Count();
}
// and map it to VM, add to list
titleVMList.Add(new TitleVM
{
TitleID = TitleID,
MeaningCount = count
});
}
return titleVMList;
}
I thought mapping it would be easiest, but have no idea how to map a viewmodel with lists in this way.
In my project I use Omu.ValueInjecter for mapping basic models, because Automapper needs full trust to run, and my host doesn't allow it.
Let me know if more information is needed.
Ok I read that its better to do an .AddRange then adding the the item with .Add each time.
I got my code down to the below:
public int CountMeanings(IEnumerable<Meaning> meanings)
{
if (meanings != null && meanings.Count() > 0)
return meanings.Count();
return 0;
}
public List<TitleVM> GetTitlesByArtistID(int artistID)
{
var titleVMList = new List<TitleVM>();
var titles = context.Titles.Where(x => x.ArtistID == artistID).AsEnumerable();
titleVMList.AddRange(titles.Select(item => new TitleVM {
TitleID = item.TitleID,
MeaningCount = CountMeanings(item.Meanings)
}));
return titleVMList;
}

ServiceStack.ORMLite: Custom query to custom Poco with Sql.In selections?

Background
I'm attempting to use ServiceStack.OrmLite to grab some values (so I can cache them to run some processing against them).
I need to grab a combination of three values, and I have a custom SQL statement that will yield them (does the joins, etc.)
Because this will be a large list of combinations, I'd like to pass in some lists of values and use Sql.In to filter to only the results that have those values.
Specifics
I need to check whether an invoice is unique to a firm and another value (called ClaimLawsuitID here).
so have my poco:
public class FirmIDClaimLawsuitIDInvoiceNumberCombination
{
public string FirmID { get; set; }
public string ClaimLawsuitID { get; set; }
public string InvoiceNumber { get; set; }
}
and I have my SQL statement:
select tblDefenseInvoice.FirmID, tblDefInvClaimantDetail.ClaimLawsuitID, tblDefInvClaimantDetail.invoiceNumber
from tblDefenseInvoice
inner join tblDefInvClaimantDetail
on(tblDefenseInvoice.DefenseInvoiceID = tblDefInvClaimantDetail.DefenseInvoiceID)
I would like to run the following:
public List<FirmIDClaimLawsuitIDInvoiceNumberCombination> GetFirmIDClaimLawsuitIDInvoiceNumberCombinationsForExistingItems(IEnumerable<int> firmIds, IEnumerable<long> claimLawsuitIDs, IEnumerable<string> invoiceNumbers)
{
var sql = #"select tblDefenseInvoice.FirmID, tblDefInvClaimantDetail.ClaimLawsuitID, tblDefInvClaimantDetail.invoiceNumber
from tblDefenseInvoice
inner join tblDefInvClaimantDetail
on(tblDefenseInvoice.DefenseInvoiceID = tblDefInvClaimantDetail.DefenseInvoiceID)";
var ev = OrmLiteConfig.DialectProvider.ExpressionVisitor<tblClaimLawsuit>();
var firmFilter = PredicateBuilder.True<tblDefenseInvoice>();
var claimLawsuitFilter = PredicateBuilder.True<tblDefInvClaimantDetail>();
var invoiceNumberFilter = PredicateBuilder.True<tblDefInvClaimantDetail>();
firmFilter = x => Sql.In(x.FirmID, firmIds);
claimLawsuitFilter = x => Sql.In(x.ClaimLawsuitID, claimLawsuitIDs);
invoiceNumberFilter = x => Sql.In(x.InvoiceNumber, invoiceNumbers);
ev.Select(sql);
ev.Where(firmFilter);
ev.Where(claimLawsuitFilter);
ev.Where(invoiceNumberFilter);
return dal.DB.Select<FirmIDClaimLawsuitIDInvoiceNumberCombination>(ev.ToSelectStatement());
}
Question
Is this possible to achieve this way?
Is there some other way of achieving this within ServiceStack's OrmLite that is cleaner and I'm unaware of?
Since I was selecting to a POCO, I simply needed to add the filters based on that POCO.
The following worked just fine:
public List<FirmIDClaimLawsuitIDInvoiceNumberCombination>
GetFirmIDClaimLawsuitIDInvoiceNumberCombinationsForExistingItems(
IEnumerable<long> firmIds,
IEnumerable<long> claimLawsuitIDs)
{
var sql = #"select tblDefenseInvoice.FirmID, tblDefInvClaimantDetail.ClaimLawsuitID, tblDefInvClaimantDetail.invoiceNumber
from tblDefenseInvoice
inner join tblDefInvClaimantDetail
on(tblDefenseInvoice.DefenseInvoiceID = tblDefInvClaimantDetail.DefenseInvoiceID)";
var ev = OrmLiteConfig.DialectProvider.ExpressionVisitor<FirmIDClaimLawsuitIDInvoiceNumberCombination>();
var firmFilter = PredicateBuilder.True<FirmIDClaimLawsuitIDInvoiceNumberCombination>();
var claimLawsuitFilter = PredicateBuilder.True<FirmIDClaimLawsuitIDInvoiceNumberCombination>();
firmFilter = x => Sql.In(x.FirmID, firmIds);
claimLawsuitFilter = x => Sql.In(x.ClaimLawsuitID, claimLawsuitIDs);
ev.Select(sql);
ev.Where(firmFilter);
ev.Where(claimLawsuitFilter);
return dal.DB.Select<FirmIDClaimLawsuitIDInvoiceNumberCombination>(ev.ToSelectStatement());
}