Use fLinq to persist? - linq

I don't see a lot of examples on how to persist with linq/flinq- I may ultimately write a proc to dowhat I need it to, however the 1->* relationship between tableA and tableC makes that tricky. Can you persist with flinq? Is there a example published somewhere I could follow? Below is what I have tried (or rather the most logical variant of what I have tried).
Thank you in advance.
TableA (1) -> (1) TableB
TableA (1) -> (*) TableC
// add the report
let b = TableB()
b.Name <- getName()
// add the authors
let authorSet = Data.Linq.EntitySet<TableC>()
getAuthorIds document.Authors |> Seq.iter
(fun id ->
let c = TableC()
c.Id <- id
authorSet.Add c)
// add the tagged report w/ associated reoprt
let a = TableA()
a.field1 <- "Something"
a.tableB = b
a.TableC <- authorSet
let docSet = Data.Linq.EntitySet<TableA>()
docSet.Add doc
db.TableA.InsertAllOnSubmit([doc])
let cf = db.ChangeConflicts
let cm = db.GetChangeSet

I am not sure what exactly you are trying to achieve and what fails, but at least one piece that is missing from your code is this call:
db.SubmitChanges()
In general, types TableA, TableB etc represent one row in the database, and type Table<TableA>, Table<TableB> etc represent the whole database. So if you want to add a row to a database TableA, you do something along the lines of
let rowA = TableA(Name = "Foo", Salary = 42)
db.TableA.InsertOnSubmit(rowA)
db.SubmitChanges()
You can of course have more changes in object model before you do SubmitChanges (i.e. you can and must add all relevant foreign-keyed entities with 1:1 relationship).
There is not much F#-specific here - MSDN is a great source for information on this, see e.g. http://msdn.microsoft.com/en-us/library/bb386941.aspx.

Related

linq query with many-to-many relationship

Let’s assume I have three tables in my database:
Authors(PK Id, AuthorName)
Books(PK Id, BookName)
Authors_Books(FK BookId, FK AuthorId)
I need to write a method which passes in a parameter int[] authorsIds and returns all books (Id, BookName, list of authors of this book) if it was written by any author whose Id contains in int[] authorsIds parameter.
I need LINQ query (query method).
I really need a help. Appreciate your help very much.
var int[] authors = { 1, 2, 3 };
var books = from book in books
where book.Authors.Any(x => authors.Contains(x.AuthorId))
select book;
PS: I assume book.Authors is your reference to Authors_Books table (or maybe has a different name).
this answer is based on the exact structure without considering that A obj has B in its structure
var book = from b in books
where book.Id in ( from ab in AuthersBooks
where selectedAuthers.contains(ab.AutherId)
select ab.bookId ) //now we have books that are authered by one of the selected authers
select new { BookId = b.Id, // now we create an anonymos object to contain any info we need
BookName = b.Name,
BookAuthers = (from a in authers
join ab in AuthersBooks
on a.Id == ab.AuthersId
where ab.bookid == b.Id
select a)
this will propably have syntax errors and after correcting you may get an error about multiple threads which already has an answer here

What tools are there that help build expression trees for dynamic LINQ queries?

My project needs to let users build their own dynamic queries. From what I've read, Expression Trees are the way to go. However the syntax is rather complicated.
I envision having a GUI where users would be able to check tables, select columns, specify parameters,etc and then build a string such as:
var myQuery =
from P in context.Projects
join UA in context.UserAttributes on P.ProjectID equals UA.ProjectID
join UBA in context.UserBooleanAttributes on UA.UserAttributeID equals UBA.UserAttributeID
join U in context.Users on UBA.UserID equals U.UserID
where P.ProjectID == 1
where UBA.Value == true
where (UA.UserAttributeID == 1 || UA.UserAttributeID == 2)
select new { uba = U };
And store that in a queries table. To process the query, I was hoping there is some library out there that will magically do something like:
var result = magic(str);
foreach(var user in result)
Foo(user.Email);
In this example I know that all my queries would return Users, but for other queries I would probably have to use reflection or in another column specify the expected type in results.
I found one project called LinqTextQueryBuilder which looks interesting, but I wanted to see if there are other alternatives.

Combining LINQ Queries to reduce database calls

I have 2 queries that work, I was hoping to combine them to reduce the database calls.
var locations = from l in db.Locations
where l.LocationID.Equals(TagID)
select l;
I do the above because I need l.Name, but is there a way to take the above results and put them into the query below?
articles = from a in db.Articles
where
(
from l in a.Locations
where l.LocationID.Equals(TagID)
select l
).Any()
select a;
Will I actually be reducing any database calls here?
This seems a bit complicated because Locations appears to be a multi-value property of Articles and you want to only load the correct one. According to this answer to a similar question you need to use a select to return them separately in one go so e.g.
var articles = from a in db.Articles
select new {
Article = a,
Location = a.Locations.Where(l => l.LocationId == TagId)
};
First failed attempt using join:
var articlesAndLocations = from a in db.Articles
join l in a.Locations
on l.LocationID equals TagID
select new { Article = a, Location = l };
(I usually use the other LINQ syntax though so apologies if I've done something stupid there.)
Could you not use the Include() method here to pull in the locations which are associated with each article, then select both the article and location object? or the properties you need from each.
The include method will ensure that you don't need to dip into the db twice, but will allow you to access properties on related entities.
You would need to use a contains method on an IEnumerable I believe, something like this:
var tagIdList = new List() { TagID };
var articles = from a in db.Articles.Include("Locations")
where tagIdList.Contains(from l in a.Locations select l.LocationID)
select new { a, a.Locations.Name };
(Untested)

Selective Linq child include two levels deep

I'm porting some sql stored procedure logic, which would return multiple tables in a dataset, to entity framework strongly typed objects, queried with linq.
Basically I need the data from tables A, B, and C, where C has a foreign key to B, and B has a foreign key to A. But I don't want every C with a FK to B, just the C's with a certain constraint X.
So basically, the stored proc basically said
TableA = select from A where A.AID = AIDPassedIn
TableB = select from B where B.AID = AIDPassedIn
TableC = select from TableB where TableB.XID = XIDPassedIn
return new DataSet(TableA, TableB, TableC);
//yes this is gross and confusing, thus our current efforts
Entity framework almost makes this super easy like so
A.Include("B.C").Where(a => a.AID == AIDPassedIn)
My only problem is that this doesn't include constraint X on the C table. I've read a bunch of articles, but everything I've read suggests things I could add to the where clause, and that would filter what A objects I end up with. I should only end up with one A object though, regardless of the properties of it's children. What I want is The A with AIDPassedIn, and all it's child B's, and all the B's children C that match constraint X.
I feel like this is one of my worst phrased questions ever but I'm at a bit of a block. Any help would be great thanks!
You can try it along the lines of the following:
var AList = context.As.Where(a => a.AID == AIDPassedIn)
.Select(a => new
{
A = a,
Bs = a.Bs,
Cs = a.Bs.Select(b => b.Cs.Where(c => c.XID == XIDPassedIn))
})
.AsEnumerable()
.Select(x => x.A)
.ToList(); // or SingleOrDefault if AIDPassedIn is the PK
Entity Framework will put the object graph together automatically (even without using Include) as long as you don't disable change tracking.

How to write linq to get data from different tables?

Suppose I have 3 tables: A(aid, ...), B(bid, ...) Relationship(aid, bid, ...)
Then I have a aid as parameter, I want to get the result from b. If use SQL, will be like
select b.* from B join Relationship on b.bid = Relationship.bid
where relationship.aid = aid_param
how to write linq with same result as above SQL. (the foreign key was not created correctly in this case)?
Assuming that you've used the designer to add your tables to the LINQ data context and you have either foreign key relationships defined in the database or have hand-coded the associations in the designer, you should simply be able to reference the B table and it's EntitySet of Relationship properties, filtered by your parameter, and check if there are any matches.
var relationships = db.B.Any( b => b.Relationships.Where( r => r.aid == aid_param ) );
var bQuery = from r in MyContext.Relationship
where r.aid == aid_param
select r.B;
If you don't have a relationship set in the model, then u can:
var bQuery = from b in myContext.B
where myContext.Relationship
.Any( r => r.aid == aid_param && b.bid == r.bid)
select b;
var output =
from b
from Relationship
where (b.bid = Relationship.bid,
relationship.aid = aid_param)

Resources