Given the classes below, I want to be able to use a List of ids to return designs that have the AttributeId of 1 or 3 in the DesignAttribute table.
public class Design
{
public int DesignId { get; set; }
public string DesignName { get; set; }
public virtual List<DesignAttribute> DesignAttributes { get; set;}
}
public class Attribute
{
public int AttributeId { get; set; }
public string AttributeName { get; set; }
}
public class DesignAttribute
{
public int DesignAttributeId { get; set; }
public virtual Design Design { get; set; }
public virtual Attribute Attribute { get; set; }
}
A design can have 1 or more attributes, for example
Design Table
DesignId DesignName
1 Design A
2 Design B
3 Design C
Attribute Table
AttributeId AttributeName
1 Light
2 Dark
3 Demo
DesignAttribute Table
DesignAttributeId Design_DesignId Attribute_AttributeId
1 1 1 Design A is Light
2 1 3 Design A is also a Demo
3 2 2 Design B is Dark
4 3 1 Design C is Light
I've got the following code
//attributes list = "[1,3] I want any designs that have Light OR Demo attributes"
public List<Design> FilterDesigns(List<string> attributes)
{
//sudo code as i'm not sure how to structure this.
var designs = db.Designs.Where(i => i.DesignAttributes
WHERE DesignAttributes.AttributeId is in the list of attributes passed into the method)
}
So i'd hopefully end up with a list of 2 items containing the designs Design A and Design C, as they both have an ID against the Attribute Id 1 and 3 in the DesignAttribute lookup table.
Try this :
var designs = db.Designs.Where(design =>
design.DesignAttributes.Any(designAttribute =>
attributes.Contains(designAttribute.Attribute.AttributeId)))
.ToList();
Try this
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ConsoleApplication29
{
class Program
{
static void Main(string[] args)
{
List<Design> designTable = new List<Design>() {
new Design() { DesignId = 1, DesignName = "A"},
new Design() { DesignId = 2, DesignName = "B"},
new Design() { DesignId = 3, DesignName = "C"}
};
List<Attribute> attributeTable = new List<Attribute>() {
new Attribute() { AttributeId = 1, AttributeName = "Light"},
new Attribute() { AttributeId = 2, AttributeName = "Dark"},
new Attribute() { AttributeId = 3, AttributeName = "Demo"}
};
List<DesignAttribute> designAttributeTable = new List<DesignAttribute>() {
new DesignAttribute() { DesignAttributeId = 1, DesignId = 1, AttributeId = 1},
new DesignAttribute() { DesignAttributeId = 2, DesignId = 1, AttributeId = 3},
new DesignAttribute() { DesignAttributeId = 3, DesignId = 2, AttributeId = 2},
new DesignAttribute() { DesignAttributeId = 4, DesignId = 3, AttributeId = 1}
};
var results = (from dattbl in designAttributeTable
join dttbl in designTable on dattbl.DesignId equals dttbl.DesignId
join attbl in attributeTable on dattbl.AttributeId equals attbl.AttributeId
select new { designName = dttbl.DesignName, attributeName = attbl.AttributeName }).ToList();
}
}
public class Design
{
public int DesignId { get; set; }
public string DesignName { get; set; }
public virtual List<DesignAttribute> DesignAttributes { get; set; }
}
public class Attribute
{
public int AttributeId { get; set; }
public string AttributeName { get; set; }
}
public class DesignAttribute
{
public int DesignAttributeId { get; set; }
public int DesignId { get; set; }
public int AttributeId { get; set; }
}
}
You can try to use this query:
var ids = new List<int> { 1, 3 };
var designs = db.DesignAttributes
.Where(m => ids.Contains(m.DesignAttributeId))
.Select(p => p.Design)
.ToList();
It will query DesignAttributes where DesignAttributeId are present in list ids. Than it will select Designs.
Related
I'm working on writing an API using .NET 6. I've encountered a "Collection was of a fixed size error" error, which I've never seen before. Looking here on SO I haven't seen anything that addresses this situation. Here's the DbContext class:
using Microsoft.EntityFrameworkCore;
namespace ECommerce.Api.Orders.Db
{
public class OrdersDbContext : DbContext
{
public OrdersDbContext(DbContextOptions dbContextOptions) : base(dbContextOptions)
{
}
public DbSet<Order> Orders { get; set; }
public DbSet<OrderItem> OrderItems { get; set; }
}
}
Here's the Order class:
namespace ECommerce.Api.Orders.Db
{
/*
* This is the in-memory class for Orders
*/
public class Order
{
public int Id { get; set; }
public int CustomerId { get; set; }
public DateTime OrderDate { get; set; }
public decimal Total { get; set; }
public ICollection<OrderItem>? Items { get; set; } }
}
And the OrderItem class:
namespace ECommerce.Api.Orders.Db
{
/*
* This is the in-memory class for OrderItems
*/
public class OrderItem
{
public int Id { get; set; }
public int OrderId { get; set; }
public int ProductId { get; set; }
public int Quantity { get; set; }
public decimal UnitPrice { get; set; }
}
}
Now comes the OrdersProvider class. In OrdersProvider I create an orderItems array, an orderItemsTotals array and 3 arrays of type OrderItem which I use to put into new values in the instances I add to the in-memory Orders table. The error comes on the second Add() method in Step 3:
private void SeedData()
{
if (!dbContext.Orders.Any())
{
// Step 1: Start by creating a collection of 3 OrderItems
OrderItem[] orderItems = new OrderItem[]
{
new OrderItem() {Id = 1, OrderId = 1, ProductId = 1, Quantity = 5, UnitPrice = 5.5M},
new OrderItem() {Id = 2, OrderId = 1, ProductId = 2, Quantity = 7, UnitPrice = 13.75M },
new OrderItem() {Id = 3, OrderId = 2, ProductId = 3, Quantity = 10, UnitPrice = 25.99M}
};
// need to get the totals of the values created above, into its own array
decimal[] orderItemTotals = new decimal[3];
for (int i = 0; i < 3; i++)
{
orderItemTotals[i] = orderItems[i].Quantity * orderItems[i].UnitPrice;
}
// Step 2: Need three separate array types to use in the creation of Orders
OrderItem[] orderItems1 = new OrderItem[2]
{
orderItems[0],
orderItems[2]
};
OrderItem[] orderItems2 = new OrderItem[2]
{
orderItems[0],
orderItems[1]
};
OrderItem[] orderItems3 = new OrderItem[1]
{
orderItems[2]
};
// Step 3: Then create a dbContext of Orders the 3 OrderItems above
dbContext.Orders.Add(new Db.Order()
{
Id = 1,
CustomerId = 1,
OrderDate = new DateTime(2022, 1, 17),
Items = orderItems1,
Total = orderItemTotals[0] + orderItemTotals[2]
});
dbContext.Orders.Add(new Db.Order()
{
Id = 2,
CustomerId = 2,
OrderDate = new DateTime(2020, 7, 1),
Items = orderItems2,
Total = orderItemTotals[0] + orderItemTotals[1]
});
dbContext.Orders.Add(new Db.Order()
{
Id = 3,
CustomerId = 3,
OrderDate = new DateTime(2018, 10, 31),
Items = orderItems3,
Total = orderItemTotals[2]
});
dbContext.SaveChanges();
}
}
At this point I don't understand why I'm getting that error when adding the second element after Step 3 in the code immediately above. I would think that Orders is a table; there should be nothing fixed about it. Or it might be related to Items in Order class, but Items is of nullable type of ICollection<OrderItem>. That shouldn't complain about being fixed, either.
So, where am I making my mistake?
Hi can someone assist please,i have a list that contain my promotions codes and in the list i would like to return only promotion codes that appear once i.e dont have duplicates,please see below data from JSON,i would like to return Promotion code A123 and B500 and store them in another list.
[
{
"PromCode": "A123",
"Priority": 1,
"offer": "Win a Free Cap",
"StartDte": "2020-08-11T00:16:23.184Z",
"endDte": "2020-09-10T17:16:23.184Z",
},
{
"PromCode": "A100",
"Priority": 1,
"offer": "Win a perfume",
"StartDte": "2020-08-11T00:16:23.184Z",
"endDte": "2020-09-10T17:16:23.184Z",
},
{
"PromCode": "A100",
"Priority": 2,
"offer": "Win a Phone pouch",
"StartDte": "2020-09-11T00:16:23.184Z",
"endDte": "2020-10-10T17:16:23.184Z",
},
{
"PromCode": "B500",
"Priority": 1,
"offer": "Win a free router",
"StartDte": "2020-08-11T00:16:23.184Z",
"endDte": "2020-09-10T17:16:23.184Z",
},
]
I have a list that contains all this promotion code as seen below
var existingProms = await _Repo.GetAllPromCodes(promCodeList);
i tried to get ones that appear once in the list like this
var appearOnce = existingProms.Count(x => existingBnplIndicators.Contains(x.PromCode)).ToList()<2;
var appearOnce = existingProms.where(x=> x.PromCode.Count()).ToList()<2;
But this did not work,there is 0 results returned,could someone show how to get my two Proms A123,B500 into my appearOnce lis.Thankst
You can use GroupBy to get all the results grouped by PromoCode. Then, filter the results based on the number of items each group has to only show when Count() == 1.
Something like this perhaps,
public class Class1
{
public string PromCode { get; set; }
public int Priority { get; set; }
public string offer { get; set; }
public DateTime StartDte { get; set; }
public DateTime endDte { get; set; }
}
var obj = JsonConvert.DeserializeObject<List<Class1>>(json);
var singlesOnly = obj.GroupBy(x => x.PromCode).Where(y => y.Count() == 1);
You should compare desired objects only by promcode implicitly. Take look how Equals and GetHashCode() works.
using System;
using System.Collections.Generic;
using System.Linq;
namespace test
{
public class TestObj : IEquatable<TestObj>
{
public string Promocode { get; set; }
public int Priority { get; set; }
public string offer { get; set; }
public DateTime StartDate { get; set; }
public DateTime endDate { get; set; }
public override int GetHashCode() => this.Promocode.GetHashCode();
public bool Equals(TestObj other) => Promocode.Equals(other.Promocode);
}
class Program
{
static void Main(string[] args)
{
var a = new TestObj()
{
Promocode = "1",
Priority = 1,
offer = "1",
StartDate = new DateTime(1, 2, 3),
endDate = new DateTime(1, 2, 3)
};
var b = new TestObj()
{
Promocode = "1",
Priority = 1,
offer = "1",
StartDate = new DateTime(1, 2, 3),
endDate = new DateTime(1, 2, 3)
};
var c = new TestObj()
{
Promocode = "2",
Priority = 1,
offer = "1",
StartDate = new DateTime(1, 2, 3),
endDate = new DateTime(1, 2, 3)
};
var list = new List<TestObj>()
{
a,
b,
c
};
var uniqueOnly = list.Distinct();
foreach (var item in uniqueOnly)
{
Console.WriteLine(item.Promocode);
}
}
}
}
First define class items-
public string PromCode { get; set; }
public int Priority { get; set; }
public string offer { get; set; }
public DateTime StartDte { get; set; }
public DateTime endDte { get; set; }
Then take multiple items in list and use distinct() function to remove duplicate values-
static void Main(string[] args)
{
List<TestClass> list = new List<TestClass>()
{
new TestClass(){PromCode="A123",Priority=1,offer="Win a Free
Cap",StartDte=new DateTime(2020-08-11),endDte=new DateTime(2020-09-10)},
new TestClass(){PromCode="A100",Priority=1,offer="Win a
perfume",StartDte=new DateTime(2020-08-11),endDte=new DateTime(2020-09-
10)},
new TestClass(){PromCode="A100",Priority=2,offer="Win a Phone
pouch",StartDte=new DateTime(2020-09-11),endDte=new DateTime(2020-10-10)},
new TestClass(){PromCode="B500",Priority=1,offer="Win a free
router",StartDte=new DateTime(2020-08-11),endDte=new DateTime(2020-09-10)}
};
var finalList = list.Select(b => b.PromCode).Distinct().ToList();
foreach(var item in finalList)
{
Console.WriteLine(item + "");
}
Console.Read();
}
}
I have simple class which represents fields in MongoDB document
class Measurement
{
public ObjectId id { get; set; }
public int s { get; set; }
public int[] p { get; set; }
public int dt { get; set; }
public int ml { get; set; }
}
I'm trying to get documents matching my conditions using
var collection = database.GetCollection<Measurement>(mongoCollectionName);
var query = from a in collection.AsQueryable<Measurement>()
where a.dt > 100
select a;
When where condition is removed i do receive all documents but with condition none. Response says there's no matching documents but there are (example dt=1538555)
query looks like this {aggregate([{ "$match" : { "dt" : { "$gt" : 100 } } }])}.
I build my example using response from this thread and mongodb documentation
MongoDB C# Aggregation with LINQ
I would be grateful with solving probably my stupid mistake
i don't use the c# driver directly anymore so my solution is using MongoDAL.
using System;
using System.Linq;
using MongoDAL;
namespace Example
{
class Measurement : Entity
{
public int s { get; set; }
public int[] p { get; set; }
public int dt { get; set; }
public int ml { get; set; }
}
class Program
{
static void Main(string[] args)
{
new DB("measurements");
var measurement1 = new Measurement
{
s = 10,
ml = 20,
dt = 100,
p = new int[] { 1, 2, 3, 4, 5 }
};
var measurement2 = new Measurement
{
s = 11,
ml = 22,
dt = 200,
p = new int[] { 1, 2, 3, 4, 5 }
};
measurement1.Save();
measurement2.Save();
var result = (from m in DB.Collection<Measurement>()
where m.dt > 100
select m).ToArray();
Console.ReadKey();
}
}
}
Assume the following model. Note the self-referencing relationship "parent".
public class Category
{
public virtual long Id { get; set; }
public virtual string Name { get; set; }
public virtual Category Parent { get; set; }
public virtual long? ParentId { get; set; }
}
My data are as follows:
id | name | parentId
1--------tag 1 ----- null
2--------tag 2 ----- 1
3--------tag 3 ----- 1
4--------tag 4 ----- 2
5--------tag 5 ----- null
6--------tag 6 ----- null
I want to write a query that data will be sorted as follows
tag 1
----->tag 2
----->----->tag 4
----->tag 3
tag 5
tag 6
This is my code
var categorys = __categories
.AsNoTracking()
.ToList();
I do not know how to sort them
Well I would describe that more as hierarchical organisation as opposed to sorting, but here is an example of how you can achieve it quite simply. Note, this is not very optimised as the search for each Parent Category requires potentially a full scan of the entire Category list, but it's a good starting point:
using System;
using System.Collections.Generic;
using System.Linq;
namespace SimpleTree
{
public class Program
{
private static void Main(string[] args)
{
var categories = new List<Category>()
{
new Category {Id = 1, Name = "tag 1"},
new Category {Id = 2, Name = "tag 2", ParentId = 1},
new Category {Id = 3, Name = "tag 3", ParentId = 1},
new Category {Id = 4, Name = "tag 4", ParentId = 2},
new Category {Id = 5, Name = "tag 5"},
new Category {Id = 6, Name = "tag 6"},
};
foreach (var category in categories)
{
category.Parent = FindParent(categories, category.ParentId);
}
//pretty printing with indentation is left as an exercise for you :)
foreach (var category in categories)
{
Console.WriteLine("ID:{0} Name:{1} ParentID:{2}", category.Id, category.Name, category.ParentId);
}
Console.ReadLine();
}
private static Category FindParent(IEnumerable<Category> categories, long? parentId)
{
if (parentId == null) return null;
return categories.FirstOrDefault(c => c.Id == parentId);
}
}
public class Category
{
public virtual long Id { get; set; }
public virtual string Name { get; set; }
public virtual Category Parent { get; set; }
public virtual long? ParentId { get; set; }
}
}
Output
ID:1 Name:tag 1 ParentID:
ID:2 Name:tag 2 ParentID:1
ID:3 Name:tag 3 ParentID:1
ID:4 Name:tag 4 ParentID:2
ID:5 Name:tag 5 ParentID:
ID:6 Name:tag 6 ParentID:
Note that depending on your use case, you might find it useful to include a ChildCategories collection on the Category object, and fill this as well, so that it's easy to walk the tree in either direction.
Try this recursive function
class Program
{
static void Main(string[] args)
{
using (var db = new aaContext2())
{
Temp temp = new Temp();
var cc = db.Catagory.FirstOrDefault();
IList<Category> parentList =new List <Category>();
foreach (Category catagory in db.Catagory.Where(cat => cat.ParentId == null))
{
parentList.Add(temp.Recursive(catagory.Id, catagory.Name));
}
}
}
}
public class Temp{
public Category Recursive(long parentId, string name)
{
Category catagory = new Category();
catagory.Id = parentId; catagory.Name = name;
using (var db = new aaContext2())
{
//base condition
if (db.Catagory.Where(catagory1 => catagory1.ParentId == parentId).Count() < 1)
{
return catagory;
}
else
{
IList<Category> newCatagoryList = new List<Category>();
foreach (Category cat in db.Catagory.Where(cata => cata.ParentId == parentId))
{
newCatagoryList.Add(Recursive(cat.Id, cat.Name));
}
catagory.CatagoryList = newCatagoryList;
return catagory;
}
}
}
}
public class aaContext2 : DbContext
{
public DbSet<Category> Catagory { get; set; }
}
public class Category
{
public virtual long Id { get; set; }
public virtual string Name { get; set; }
public virtual Category Parent { get; set; }
public virtual ICollection<Category> CatagoryList { get; set; }
public virtual long? ParentId { get; set; }
}
I have a an object Quiz that looks like :
public class Quiz
{
public int Id { get; set; }
public ICollection<MathQuiz> MathQuizzes { get; set; }
}
MathQuizze object looks like :
public class MathQuiz
{
public int Id { get; set; }
public int QuizId{ get; set; }
public Quiz Quiz{ get; set; }
public int AnswerId { get; set; }
public Answer Answer { get; set; }
public int TagId{ get; set; }
public Tag Tag { get; set; }
public bool IsCorrect { get; set; }
}
And have an object(UserQuizzes) that looks like:
public class UserQuizes
{
public int Id { get; set; }
public int UserId { get; set; }
public User User { get; set; }
public int QuizId { get; set; }
public Quiz Quiz { get; set; }
}
UserQuizzes is just class that express many to many relationship between users and quizzes.
This is a sample data :
List<Quiz> quizzes = new List<Quiz>();
quizzes.Add(new Quiz{ Id = 1, MathQuizzes = new List<MathQuiz>{
new MathQuiz { AnswerId = 58, TagId = 1, IsCorrect = false },
new MathQuiz { AnswerId = 26, TagId = 2, IsCorrect = true },
new MathQuiz { AnswerId = 57, TagId = 3, IsCorrect = true },
new Quiz{ Id = 2, MathQuizzes = new List<MathQuiz>{
new MathQuiz { AnswerId = 59, TagId = 1, IsCorrect = false },
new MathQuiz { AnswerId = 87, TagId = 2, IsCorrect = true },
new MathQuiz { AnswerId = 25, TagId = 3, IsCorrect = true }, });
List<UserQuizzes> userQuizzes = new List<UserQuizzes>();
userQuizzes.Add(new Quiz{ QuizId = 1, UserId = 1},
userQuizzes.Add(new Quiz{ QuizId = 2, UserId = 1});
Please don't spend too much time criticizing, I just wanted to use something that everyone is pretty familiar with.
What i want to achieve is that group by userquizzes by MathQuiz TagId and get data something like this:
TagId : 1, IsCorrect: true(0), false(2);
TagId : 2, IsCorrect: true(2), false(0);
TagId : 3, IsCorrect: true(2), false(0);
The code you posted has typos, but here is the basic idea:
var query =
from q in quizzes
from mq in q.MathQuizzes
join uq in userQuizzes on q.Id equals uq.QuizId
group mq by mq.TagId into g
select new
{
TagId = g.Key,
Correct = g.Sum(e => e.IsCorrect ? 1 : 0),
Incorrect = g.Sum(e => e.IsCorrect ? 0 : 1)
};
Basically you need to get the effective source set by joining the data sets, and the do the regular grouping/calculating aggregates.