ASP NET CORE - Using EF Core
Table:
UserBooksId - Primary Key
UserId - the userId from another table
BookId - the bookId from another table
BookToBuy - where i keep my content
NrBooksOrdered - the number of the books ordered
So I don't know how to acces the content of this table using the UserId - > BookToBuy and NrBooksOrdered or even all the Primary Keys that have this userId.
Primary Key being unique, doesn't help me to much, because in the database, the UserId can be in the database multiple times, as well the bookid.
Example:
UserBookId:0 | UserId:1 | BookId:2 | BookToBuy:Wizzard | NrBooksOrdered:2
UserBookId:1 | UserId:1 | BookId:2 | BookToBuy:Wizzard | NrBooksOrdered:6
UserBookId:2 | UserId:1 | BookId:3 | BookToBuy:LongRoad | NrBooksOrdered:1
As you can see the UserId doesn't change.
Thank you.
You can use basic linq queries here
/* b is a reference here to every book, so you can filter it by the bool-expression */
var booksQuery = dbcontext.BooksTable.Where(b => b.UserId == 1 && b.BookId == 2);
/* books will be type of IQueryable so it isnt retrieved from the database */
/* yet. To do so, you can use `.ToList()` or `.AsEnumerable()` (wich is */
/* faster in use-cases, where you need to iterate the result once) */
var booksFromDb = booksQuery.AsEnumerable();
For a detailed description, on how to query data with EF-Core you can always refer back to: MS-Docs Querying Data
Related
Ok, so first of I would like to say that I'm using NHibernate for my project, and in this project we have (among other things) a sync function (to sync from a central MSSQL database to a local SQLite). Now I know that NHibernate was not made to sync databases, but I would like to do this anyways.
I have a medium large database model so I can't add it here, but the problem is that I have two datatables, and one link table to link them both.
Database model:
| Product | | ProductLinkProducer | | Producer |
|--------------------| |---------------------| |---------------------|
| Id | | LinkId | | Id |
| Name | | Product | | Name |
| ProductLinkProducer| | Producer | | ProductLinkProducer |
Database:
| Product | | ProductLinkProducer | | Producer |
|---------| |---------------------| |----------|
| Id | | LinkId | | Id |
| Name | | ProductId | | Name |
| | | ProducerId | | |
So during the sync, I first copy all data from the Product table, and then from the Producer table (basically var products = session.Query<Products>().ToList()). This is done by NHibernate in a single statement each:
select
product0_.id as id2_,
product0_.name as name2_
from
Product product0_
Now I have to evict all items from the first session (products.ForEach(x => session.Evict(x));)
And then the save (products.ForEach(x => syncSession.save(x));) is one insert per row (as expected).
So when saving the data in the link table I would have wished that there also would be just a single select. However that is not the case. Because first it makes a select ... as above. But now before every row to insert it does even more select for the Product and for the Producer.
So it will look something like:
Products:
select
insert (id 1)
insert (id 2)
Producer:
select
insert (id 101)
insert (id 102)
ProdLinkProducer:
select
select id 1 from Products
select id 1 from Products
select id 101 from Producer
select id 2 from Products
select id 2 from Products
select id 102 from Producer
select id 102 from Producer
insert
insert
So is there anyway avoiding this behavior?
EDIT
To better explain what I have done, I have created a small test project. It can be found here: https://github.com/tb2johm/NHibernateSync
(I would have preferred to add only a ghist, but I think that it might have left out to much data, sorry...)
EDIT2
I have found out one way to make it work, but I don't like it.
The way this solution works is to in the database model create a ProductLinkProducerSync table, that doesn't contain any links, but just the values, and avoid synchronizing the ordinary link tables, but just the "sync" tables. But as I said I don't like this idea, since if I change anything in the database, I have kind of the same data in two places that I need to update.
I was unable to find NHibernate out of the box way of doing what you are asking.
However I was able to get the desired behavior (I guess something is better than nothing:) by manually rebinding the FK references (proxy classes) to the new session:
var links = session.Query<ProductLinkProducer>().ToList();
links.ForEach(x => session.Evict(x));
foreach (var link in links)
{
link.Product = syncSession.Get<Product>(link.Product.Id);
link.Producer = syncSession.Get<Producer>(link.Producer.Id);
syncSession.Save(link);
}
syncSession.Flush();
Here is the generalized version using NHibernate metadata services:
static IEnumerable<Action<ISession, T>> GetRefBindActions<T>(ISessionFactory sessionFactory)
{
var classMeta = sessionFactory.GetClassMetadata(typeof(T));
var propertyNames = classMeta.PropertyNames;
var propertyTypes = classMeta.PropertyTypes;
for (int i = 0; i < propertyTypes.Length; i++)
{
var propertyType = propertyTypes[i];
if (propertyType.IsAssociationType && !propertyType.IsCollectionType)
{
var propertyName = propertyNames[i];
var propertyClass = propertyType.ReturnedClass;
var propertyClassMeta = sessionFactory.GetClassMetadata(propertyClass);
yield return (session, target) =>
{
var oldValue = classMeta.GetPropertyValue(target, propertyName, EntityMode.Poco);
var id = propertyClassMeta.GetIdentifier(oldValue, EntityMode.Poco);
var newValue = session.Get(propertyClass, id);
classMeta.SetPropertyValue(target, propertyName, newValue, EntityMode.Poco);
};
}
}
}
and applying it to your Sync method:
private static void Sync<T>(string tableName, ISession session, ISession syncSession)
{
Console.WriteLine("Fetching data for ####{0}####...", tableName);
var sqlLinks = session.Query<T>();
var links = sqlLinks.ToList();
Console.WriteLine("...Done");
Console.WriteLine("Evicting data...");
links.ForEach(x => session.Evict(x));
Console.WriteLine("...Done");
Console.WriteLine("Saving data...");
var bindRefs = GetRefBindActions<T>(syncSession.SessionFactory).ToList();
foreach (var link in links)
{
foreach (var action in bindRefs) action(syncSession, link);
syncSession.Save(link);
}
Console.WriteLine("...Flushing data...");
syncSession.Flush();
Console.WriteLine("...Done");
Console.WriteLine("\n\n\n");
}
I'll create an Issue table in an MVC5 application and I want to use special code for each type of the issues as below:
For IT related questions INF-0001, INF-0002, ...
For General type of questions GEN-0001, GEN-0002, ...
As I use all the issues on the same table, I think it is better to store the ID numbers as INF-0001, GEN-0001, ... etc. In that case should I use string as the data type of ID column in MSSQL? Or what is the best approach in order to store Id's with their related codes? I also think of using GUID, but I am not sure if it is possible. Thanks in advance.
I suppose it's better create separate field for your custom names. So your table will have int Id (Primary Key) field and CustomName varchar(100) or nvarchar(100) type (If you use unicode characters) field with your custom names.
It will be better for perfomance to use int as Id if you will JOIN your file table with others. If you want to search values in this field and it is slow just create INDEX.
You could have a general issue id and a category, for example:
Table: Issue
------------------------------------
IssueID | CategoryID | CategoryIndex
------------------------------------
1 | 1 | 1
2 | 1 | 2
3 | 2 | 1
4 | 1 | 3
Table: Category
-----------------------------
CategoryID | Prefix | Name
-----------------------------
1 | INF | IT
2 | GEN | General
Then you calculate the issue number when querying these tables.
You can store the calculated number in a table if you want to keep track of the issue number in case of a change in the database (ex: the prefix for IT related questions changes from INF to IT)
Now that you have a good schema, how do you keep control of the category sequence on the issues table? Check this out:
DECLARE #categoryID INT
DECLARE #nextSequence INT
SET #categoryID = 1 --You'll have to change this!
SELECT #nextSequence = i.CategoryIndex
FROM Issue i
WHERE i.CategoryID = #categoryID
SELECT COALESCE(#nextSequence, 0) + 1 as 'NextSequence'
You can turn that into a stored procedure (NextSequence, maybe?) that receives an INT as parameter (the category ID) and returns another INT as result (the CategoryIndex for the new issue).
Finally, to create your full code:
SELECT
i.IssueID
, c.Prefix + '-' + RIGHT('0000' + CONVERT(VARCHAR(4), i.CategoryIndex), 4) as 'IssueCode'
FROM Issue i
INNER JOIN Category c ON i.CategoryID = c.CategoryID
I have a table that I'm trying to query using Linq to SQL
The table is very simple it has 5 columns:
- PersonID
- ADID
- Name
- PlaceID
- PlaceName
I have 2 records in my table and they have the same PersonID in both records but different PlaceID and PlaceName values:
001 | 001 | Person X | P01 | Place 1
001 | 001 | Person X | P02 | Place 2
When I query this in SQL I get exactly the 2 rows:
select * from myTable where PersonID = '001'
However, when I try to do it in LINQ:
List<myTable> PersonInfo = (from myInfo in db.myTable
where myInfo.PersonID == "001"
select myInfo).ToList();
I get a count of 2 in PersonInfo but they are the same record. What am I doing incorrectly?
What I found out was that 1st Entity Framework needs a primary key to operate correctly. After researching the table I was using I found out that there was a primary key but it was a combo key So once I put "Entity Keys" on both columns my select statement returned the correct data.
Thanks to #GertArnold and everyone else that helped me on this problem!
I have a table as follows:
ConfigID | VersionNo | ObjectType
ConfigID and VersionNo constitute the unique key.
I want to be able to select the record with the highest VersionNo for each configID based on an object type.
I have tried
configs = (from config in configRepository.FindBy(x => x.ObjectType.Equals(typeof(Node).ToString(), StringComparison.InvariantCultureIgnoreCase))
group config by config.ConfigID into orderedConfigs
select orderedConfigs.OrderBy(x => x.ConfigID).ThenByDescending(x => x.VersionNo).First());
EDIT: I must add that the FindBy is basically just a where clause.
But I am getting no results. Please help me with this.
EDIT:
The data in the table could look like:
3fa1e32a-e341-46fd-885d-8f06ad0caf2e | 1 | Sybrin10.Common.DTO.Node
3fa1e32a-e341-46fd-885d-8f06ad0caf2e | 2 | Sybrin10.Common.DTO.Node
51d2a6c7-292d-42fc-ae64-acd238d26ccf | 3 | Sybrin10.Common.DTO.Node
51d2a6c7-292d-42fc-ae64-acd238d26ccf | 4 | Sybrin10.Common.DTO.Node
8dbf7a33-441f-40bc-b594-e34c5a2c3f51 | 1 | Some Other Type
91413e73-4997-4643-b7d2-e4c208163c0d | 1 | Some Other Type
From this I would only want to retrieve the second and fourth records as they have the highest version numbers for the configID and are of the required type.
Not sure if 100% works because writing out of VS :) but idea should be good
var configs = configRepository.Where(x=>x.ObjectType==typeof(Node).ToString());
var grouped = configs.GroupBy(x=>x.ConfigId);
var a = grouped.select(x=>x.OrderByDescending(y=>y.VersionNo).First());
It looks LINQ sql to but in pure SQL i can write the query like this
SELECT ConfigID ,MAX(VersionNo ) FROM CUSTOMIZE_COLUMNS_DETAIL WHERE
ObjectType = 'objectType' GROUP BY ConfigID
I have tried to replicate the scenario in sql , might by useful to you, THanks
i have a trouble to write a query with Linq i explain better my case, i have a database with 2 tables as follow :
it is the first table ;
Hotel
HotelID (Nvarchar(10) - PK)
HotelName (Nvarchar (200))
and this one is the second table ;
Period
PeriodID (Int (inc) - PK)
_From (Datetime )
_To (Datetime)
HotelID(Nvarchar(10) - FK)
then in the second Table (Period) there is the FK (HotelID) to connect the 2 tables;
Happen sometime i have a HotelName that gets more periods(PeriodID) so my purpose is to show the data in an only one Row into a DataGrid, i show you an example as i want show the data in my DataGrid if there are more periods in the same HotelName:
| HotelName | From | To | From(2) | To(2) | From(3) | To(3) | From(4)| To(4) |
| Excelsior |12/5/10 |3/6/10 | 2/8/10 | 9/9/10 | 23/9/10 | 1/10/10| 2/11/11| 1/12/10|
so i ask do you have any idea/suggest about how to show the data in a DataGrid inside one Row using Linq To Sql ?
thanks so much for your attention .
Have a good time .
Cheers
This article explains working with hierarchical data binding: http://msdn.microsoft.com/en-us/library/aa478959.aspx
Then, create an object model which roughly maps to your database tables:
Hotel
- ID
- Name
- Bookings
- Booking 1 { From, To }
- Booking 2 { From, To }
- Booking n { From, To }
Your Linq should look something like this:
var hotels = _db.Hotel.Select();
foreach(var hotel in hotels)
hotel.Bookings = _db.Period.Where(x => x.HotelId == hotel.HotelId).Select();