To clear up the obvious first, I am:
using System.Linq;
using System.Collections.Generic;
Have a project reference to System.Core
My DbSet and DbContext classes are defined properly
The strange thing is, intellisense sees it, but I have a compiler warning and it won't compile.
I have tried cleaning the project first, restarting Visual Studio, etc and it still is complaining about:
Error CS1929 'DbSet' does not contain a definition for 'ToList' and the best extension method overload 'Enumerable.ToList(IEnumerable)' requires a receiver of type 'IEnumerable'
My "receiver" in this case is the compiler statically-determined var.
This is a new laptop and a fresh Visual Studio install ... is there something obvious I am missing here?
I wanted these internal but tried switching everything pubilc just to be sure, but I am getting the same error.
Most people report this when they are missing the using clause for Linq but I have that, and intellisense sees it which is where I am getting confused.
Line in question:
var excludedUrls = db.ExcludedUrls.ToList<string>();
I assume that in your code db is a Dbcontext with a property ExcludedUrls of type DbSet<TEntity>
DbSet<TEntity> implements IEnumerable<TEntity> If you have included LINQ, you can use the extension method Enumerable.ToList<TEntity>().
Because of your error I assume that TEntity is not a string. Your code will compile if you leave out the part:
var excludedUrls = db.ExcludedUrls.ToList();
However, this might not give a list with the elements you want. Somehow you'll have to convert each excludedUrl in your source sequence to the string representation that you want. If ToString() does not do this, you'll have to create a function yourself:
class MyDbContext : DbContext
{
public DbSet<MyTSource> ExcludedUrls {get; set;}
}
void string Transform(MyTSource excludedUrl)
{
...
}
List<string> result = dbContext.ExcludedUrls
.Select(excludedUrl => Transform(excludedUrl)
.ToList();
In words: from the sequence of excludedUrls, take each element, and transform it to a string using Transform. Convert the resulting sequence of strings to a list, which will be a list of strings
By the way, did you notice I used ToList without mentioning <string>? The compiler is able to detect the type of the elements in your input sequence, and can create a List of the same type of elements.
Consider avoiding mentioning the TSource when using the Linq functions. This has several advantages:
less typing
Easier to change the source sequence, or intermediate linq statements
Easier to detect the resulting type (and thus easier to detect the error you mentioned)
It allows the use of anonymous types
The answer, it turns out, is not calling the generic form of ToList<> here, but instead calling straight ToList(), which returns a generic List<ExcludedUrl>. A thank you to Ivan Stoev in the comments section for the tip.
I was relying too much on Intellisense hints here and not enough on memory.
As you can see, due to the way extension methods work, it presented me with a ToList in its generic form, which is why my code was written the way it was.
Related
Starting with an object mapping that was working perfectly fine for SqlLite, I tried to use the same code with Oracle, and found out that, by default, all of my string fields were mapped to VARCHAR2(255). While that works out fine for most of the fields, it's way too small for one field.
I thought it would be a simple matter to make the field bigger. Hah!
I tried this:
Property(prop => prop.BigField, map =>
{
map.Column("BIG_FIELD");
map.Length(65535);
map.Type<NHibernate.Type.StringType>();
});
This produces this error:
NHibernate.MappingException : Could not instantiate IType StringType: System.MissingMethodException: No parameterless constructor defined for this object.
A few of my search results have told me that I should use NHibernateUtil.String instead of NHibernate.Type.StringType. But all that gets me is this:
What's really weird is that I get String as an autocompletion suggestion, but then I can't use it. I tried to see if the code would compile in spite of the red squiggly line, but it doesn't. I also tried StringClob, with the same results.
Any helpful suggestions? All I want to do is make this string bigger than 255 characters. I didn't expect something so simple to fight back so hard.
To use types provided inside NHibernateUtil class use overload taking persistent type as parameter and not inside generic definition:
Property(prop => prop.Property, map =>
{
map.Type(NHibernateUtil.String);
map.Length(length);
});
In you case it seems it makes sense to map it to NHibernateUtil.StringClob:
Property(prop => prop.BigField, map =>
{
map.Column("BigField");
map.Type(NHibernateUtil.StringClob);
});
And there is nothing weird that code is not compiling inside generic for map.Type<NHibernateUtil.String>(); - generic definition expects type (like string) and not instance of type (like "value") which you are trying to supply
This isn't a full answer (so I'm still curious why I had the above problems), but this workaround is good for now:
Property(prop => prop.BigField, map =>
{
map.Column("BigField");
map.Length(65535);
});
The schema shows that the field becomes a CLOB object, and that's just fine for me for this application.
I am trying to check whether a SearchResultEntry contains a certain attribute. For this, I am trying the following code:
if(searchResultEntry.Attributes.AttributeNames.Contains(propertyName))
but this fails with the error
ICollection does not contain a definition for Contains, and the best extension method overload "Queryable.Contains<string>(IQueryable<string>, string)" requires a receiver of type "IQueryable<string>".
I also tried to make it an IQueryable using AttributeNames.AsQueryable(), but on that IQueryable, Contains is not available as well.
What is wrong here? When IntelliSense tells me something is available, but then, when I got to that very type, it is still unavailable, am I missing some references or using directives?
In LINQ to SQL, my understanding is that when I want to insert a collection of objects I am going to be using InsertAllOnSubmit. What I don't understand is when would I need to use InsertAllOnSubmit<T> as opposed to using just InsertOnSubmit?
What are the differences in either or with respect to the generic type parameter.
From LINQ definition,
public void InsertAllOnSubmit<TSubEntity>(IEnumerable<TSubEntity> entities)
where TSubEntity : TEntity;
using like this:
db.SlickTableEntries.InsertAllOnSubmit<SlickTableEntry>(entries);
db.SubmitChanges();
vs. using it like this:
db.SlickTableEntries.InsertAllOnSubmit(entries);
db.SubmitChanges();
entries is a List<SlickTableEntry>.
How should I properly use this? Which version is better?
It is a convenience method that allows you to insert multiple entities in one call. This saves you the foreach loop. It does not change the way the database is accessed but it might be a little less CPU efficient according to the decompiled code (tiny effect).
The generic type parameter exists so that you can pass a derived type if your entities are in an inheritance relationship. Starting with C# covariance support this is no longer needed.
Which one should be used in what situation?
If you have a list of entities use the list version. Otherwise, use the single item version. Do not specify the generic type argument. It is never required and just clutters the code.
There is no functional difference whatsoever. If it compiles it works. Just leave out the type argument and the compiler fills it in appropriately.
I decided that constantly writing a long winded code to select data from a table was a bad method to use when I am constantly having to reference between tables, therefore I decided to write a class that handles the queries for me and returns the rows.
public Database(object query, object name)
{
var tbl = (from c in db.name where query select c).ToArray();
return tbl;
}
I am sort of new to Entity and am having a hard time trying to understand the type name should be.
At first I tried object which gave me this error:
'Model.Container' does not contain a definition for 'name' and no extension method 'name' accepting a first argument of type 'Model.rkdb_07022016Entities2' could be found (are you missing a using directive or an assembly reference?)
So I knew that the table name I am selecting from cannot be passed through as type object.
I took an educated guess and tried to make name type Queryable but still no luck.
Could anyone possibly point me in the right direction and add some references where I can maybe learn how to tackle these situations in the future?
Thank-you.
(putting as an answer for future viewers)
You probably want an Expression<Func<EntityType, bool>>
If you need to make it generic, you could build something with T.
As I said in the comment, it's worth taking a look at Joseph Albahari's PredicateBuilder for sample code (or indeed use it as it is powerful)
I have a setup where I used Linq2SQL inheritance. To make queries easier, I expose the derived types in the DataContext as well, like the following:
public IQueryable<Derived> Derivations
{
get { return Bases.OfType<Derived>(); } // filter list on type
}
Calling this works perfectly, and I can see the SQL being correctly generated. The backing type is DataQuery<T>.
The problem comes in when I assigning this IEnumerable to a datasource (either a control or a BindingSource).
From what I can see, the DataQuery object is queried for an IListSource. And it happily supplies this. Then it proceeds to make a BindingList, which fails as the type parameter of the 2 arguments supplied (IEnumerable<Derived> and Table<Base>) does not match. It raises an exception of MissingMethod as the constructor cannot be found.
The simple workaround is just to call ToList() on the IQueryable<Derived> before assigning to the datasource and then it works, but this is quite tiring.
Any suggestions to handle this without 'loosing' the IQueryable?
Thanks
leppie
UPDATE:
The bug has now been reported to MS. More details here. Thanks Marc!
Confirmed. Looks like a bug to me; you should log it on Connect. The team are fixing LINQ-to-SQL bugs, so it might not be ignored. For now, use .ToList() etc.
Sample code:
using (var ctx = new MyDataContext())
{
var qry = ctx.BaseEntities.OfType<DerivedEntity>();
IListSource ls = (IListSource)qry;
IList list = ls.GetList(); // boom
/* Constructor on type
'System.Data.Linq.Provider.DataBindingList`1[snip]'
not found.*/
}
I had the same issue (still not fixed MS guys!).
To keep the IQueryable I did a .Cast<object>() when assigning to the datasource (i use it to output a xls file from any L2S table i want in a DynamicData website).