Format: WebGrid How To use? - asp.net

I am developing with MVC, and have a view "List"
[...]
var columns = new WebGridColumn[] {
grid.Column("Id"),
grid.Column("Descricao"),
grid.Column("UsuarioModificacao"),
grid.Column("DataModificacao"),
grid.Column("UltimoLogAcesso.DataAcesso"),
grid.Column("UltimoLogAcesso.Ip"),
grid.Column("UrlChamadaAlerta", format: (grid) => string.Format("{Id}")),
grid.Column("FlagBloqueioPainel"),
grid.ButtonColumn("ico_permission.gif", x => Url.Action("ConfirmarExclusao", "PainelChamada", new { id = x.Id } ), updateTargetId: "console"),
I need to format the UrlChamadaAlerta column that should be in this format:
painel.ejis.com.br/?id=<PainelChamada.ID>&token=<PainelChamada.GuidPainelChamada >
I will use the ID and the Guid that are in the model "PainelChamada"
public int Id {get; set;}
public System.Guid Guid { get; set; }
create routes is right, but for now the format will suit my intent.
Obs .: will be used as the format certain properties that would be made to the routes need not be perfect.
My Format is wrong, but my difficulty is to set the correct expression.

Something like this should work.
grid.Column("UrlChamadaAlerta",
format: dataItem =>
string.Format("painel.ejis.com.br?id={0}&token={1}",
dataItem.Id,
dataItem.Guid),
Note that lambda in format parameter expects a data item, which gives you a direct access to the fields you need.

Related

How to get string[] array from database with EF core [duplicate]

How can I store an array of doubles to database using Entity Framework Code-First with no impact on the existing code and architecture design?
I've looked at Data Annotation and Fluent API, I've also considered converting the double array to a string of bytes and store that byte to the database in it own column.
I cannot access the public double[] Data { get; set; } property with Fluent API, the error message I then get is:
The type double[] must be a non-nullable value type in order to use
it as parameter 'T'.
The class where Data is stored is successfully stored in the database, and the relationships to this class. I'm only missing the Data column.
You can do a thing like this :
[NotMapped]
public double[] Data
{
get
{
string[] tab = this.InternalData.Split(',');
return new double[] { double.Parse(tab[0]), double.Parse(tab[1]) };
}
set
{
this.InternalData = string.Format("{0},{1}", value[0], value[1]);
}
}
[EditorBrowsable(EditorBrowsableState.Never)]
public string InternalData { get; set; }
Thank you all for your inputs, due to your help I was able to track down the best way to solve this. Which is:
public string InternalData { get; set; }
public double[] Data
{
get
{
return Array.ConvertAll(InternalData.Split(';'), Double.Parse);
}
set
{
_data = value;
InternalData = String.Join(";", _data.Select(p => p.ToString()).ToArray());
}
}
Thanks to these stackoverflow posts:
String to Doubles array and
Array of Doubles to a String
I know it is a bit expensive, but you could do this
class Primitive
{
public int PrimitiveId { get; set; }
public double Data { get; set; }
[Required]
public Reference ReferenceClass { get; set; }
}
// This is the class that requires an array of doubles
class Reference
{
// Other EF stuff
// EF-acceptable reference to an 'array' of doubles
public virtual List<Primitive> Data { get; set; }
}
This will now map a single entity (here 'Reference') to a 'list' of your Primitive class. This is basically to allow the SQL database to be happy, and allow you to use your list of data appropriately.
This may not suit your needs, but will be a way to make EF happy.
It would be far easier if you use List<double> rather then double[]. You already have a table that stores your Data values. You probably have foreign key from some table to the table where your double values are stored. Create another model that reflects the table where doubles are stored and add foreign key mappings in the mappings class. That way you will not need to add some complex background logic which retrieves or stores values in a class property.
In my opinion almost all other answers work on the opposite of how it should be.
Entity EF should manage the string and the array must be generated from it. So the array must be whole read and written only when the string is accessed by EF.
A solution involving logic on Data[] is wrong because, as I wrote in a comment, you would run into paradoxical conditions. In all other conditions the variable must remain a pure array.
By putting the "get" and "set" logic in Data[], as I've seen so far, this happens:
1 - Every time an index access is made to the array, the array is automatically recreated from the string. This is a useless work, think of an iteration in a loop...
2 - when you go to set a single element it is not stored because it passes through "get" and not "set".
If you try to declare Data=new []{0,0,0} then set Data[1]=2 , going to re-read Data[1] the result is 0.
My solution is to completely turn the logic around.
public string Data_string
{
get => string.Join(';', Data??Array.Empty());
set => Data= value == null ? Array.Empty<double>() : Array.ConvertAll(value.Split(';',StringSplitOptions.RemoveEmptyEntries), double.Parse);
}
[NotMapped]
public double[] Data {get;set;}
Obviously this only applies to storing and retrieving data on databases, access to Data_string is exclusive to EF.
Once the string is read from the DB it is associated to Data_string which, through set, creates the Data array.
At this point you can work on Data without affecting the string in any way, like a normal array.
When you will ask EF to save in the DB, through the get in the Data_string property, the string will be completely reconstructed based on the Data elements and then stored as a string.
Practically the string is modified only twice, at the moment of reading from the DB and at the moment of saving.
In my opinion this solution is much more efficient than operating continuously on the string.
Nathan White has the best answer (got my vote).
Here is a small improvement over Joffrey Kern's answer to allow lists of any length (untested):
[NotMapped]
public IEnumerable<double> Data
{
get
{
var tab = InternalData.Split(',');
return tab.Select(double.Parse).AsEnumerable();
}
set { InternalData = string.Join(",", value); }
}
[EditorBrowsable(EditorBrowsableState.Never)]
public string InternalData { get; set; }
Don't use double[] use List insted.
Like this.
public class MyModel{
...
public List<MyClass> Data { get; set; }
...
}
public class MyClass{
public int Id { get; set; }
public double Value { get; set; }
}
All that solution that I see there are bad, because:
If you create table, you don't want to store data like this: "99.5,89.65,78.5,15.5" that's not valid! Firstly its a string that means if you can type letter into it and at the moment when your ASP.NET server call double.Parse it will result in FormatException and that you really don't want!
It's slower, because your server must parse the string. Why parse the string instead getting almost ready data from SQL Server to use?
i know this post is Ancient, but in case someone still needs to do something like this, PLEASE DO NOT USE THE ABOVE SOLUTIONS,
as the above solutions are EXTREMELY inefficient (Performance and Disk Space wise).., the best way is to store the array as a Byte array
public byte[] ArrayData;
[NotMapped]
public double[] Array {
get {
var OutputArray = new double[ArrayData.Length / 8];
for (int i = 0;i < ArrayData.Length / 8;i++)
OutputArray[i] = BitConverter.ToDouble(ArrayData, i * 8);
return OutputArray;
}
set {
var OutputData = new byte[value.Length * 8];
for (int i = 0;i < value.Length;i++) {
var BinaryValue = BitConverter.GetBytes(value[i]);
OutputData[(i*8)] = BinaryValue[0];
OutputData[(i*8)+1] = BinaryValue[1];
OutputData[(i*8)+2] = BinaryValue[2];
OutputData[(i*8)+3] = BinaryValue[3];
OutputData[(i*8)+4] = BinaryValue[4];
OutputData[(i*8)+5] = BinaryValue[5];
OutputData[(i*8)+6] = BinaryValue[6];
OutputData[(i*8)+7] = BinaryValue[7];
}
ArrayData = OutputData;
}
}
`
And if you need more performance, you can go for Unsafe code and use pointers .. instead of BitConverter ..
This is way better than saving double values (that can get huge) as string, then spliting the string array !! and then parsing the strings to double !!!
These getter/setters work on the whole array, but if you need to get just one item from the array, you can make a function that gets a single item from the array with a complexity of O(1) :
for Get :
public double Array_GetValue(int Index) {
return BitConverter.ToDouble(ArrayData, Index * 8);
}
for Set :
public void Array_SetValue(int Index, double Value) {
var BinaryValue = BitConverter.GetBytes(Value);
ArrayData[(Index*8)] = BinaryValue[0];
ArrayData[(Index*8)+1] = BinaryValue[1];
ArrayData[(Index*8)+2] = BinaryValue[2];
ArrayData[(Index*8)+3] = BinaryValue[3];
ArrayData[(Index*8)+4] = BinaryValue[4];
ArrayData[(Index*8)+5] = BinaryValue[5];
ArrayData[(Index*8)+6] = BinaryValue[6];
ArrayData[(Index*8)+7] = BinaryValue[7];
}
If your collection can be null or empty, and you want this to be preserved, do this:
[NotMapped]
public double[] Data
{
get => InternalData != null ? Array.ConvertAll(Data.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries), double.Parse) : null;
set => InternalData = value != null ? string.Join(";", value) : null;
}
Also, specify [Column(TypeName = "varchar")] on the string property for a more efficient storage data type.
A perfect enhancement to #Jonas's answer will be to add the necessary annotations. So, a cleaner version would be
[EditorBrowsable(EditorBrowsableState.Never)]
[JsonIgnore]
public string InternalData { get; set; }
[NotMapped]
public double[] Data
{
get => Array.ConvertAll(InternalData.Split(';'), double.Parse);
set
{
InternalData = string.Join(";", value.Select(p => p.ToString(CultureInfo.InvariantCulture)).ToArray());
}
}
The [JsonIgnore] Annotation will ignore the InternalData field from JSON serialization and Swagger UI.
[EditorBrowsable(EditorBrowsableState.Never)] will hide the public method from the IDE IntelliSense

Compare Dates using LINQ

I have a table, which has columns ItemName, purchaseDate and expiryDate. Essentially what i'm trying to do is write a LINQ query that counts and displays all items that are within 45days or less from their expiry date, comparing them using their purchase date.
So far this is what i've been able to do:
public string stringExpiry { get; set; }
public int intExpiry { get; set; }
intExpiry= _context.GetMyItems.Where(p => p.ExpiryDate <= p.PurchaseDate.AddDays(-45)).Count();
stringExpiry= _context.GetMyItems.Where(p=> p.ExpiryDate<=p.PurchaseDate.AddDays(-45)).ToList();
Let's make this a little bit more generic, so you can use it as any other LINQ method. After that we can specialize in a method for your class
LINQ is defined using extension methods. If you are not familiar how to create an extension method, read Extension Methods Demystified
For the examples I use the following class. Any class with two DateTime properties will do
class PurchasedProduct
{
public string Name {get; set;}
public DateTime PurchaseDate {get; set;}
public DateTime ExpiryDate {get; set;}
}
Our goal is a method that does the following:
TimeSpan maxTime = TimeSpan.FromDays(45);
IEnumerable<PurchardProduct> purchasedProducts = ...
IEnumerable<PurchasedProducts> almostExpiredProducts =
purchasedProducts.WhereAlmostExpired(maxTime);
Here we go!
First a method that says whether a class with two DataTimes is near expiry date:
public static bool IsWithinTimeSpan<T>(this T source,
Func<T, DateTime> startDateSelector,
Func<T, DateTime> endDateSelector,
TimeSpan maxTime)
{
return startDateSelector(source) - endDateSelector(source) < maxTime;
}
In words: take your source. Use the startDateSelector to extract the startDate; Use the endDateSelector to extract the endDate. Subtract these two DateTimes, and return true if the result is less than maxTime;
Usage:
PurchasedProduct purchasedProduct = new PurchasedProduct {...};
bool productNearExpiryDate = product.IsWithinTimeSpan(maxTime);
Well, if we can do this with one T, we can do this with a sequence of T:
public static IEnumerable<T> WhereWithinTimeSpan<T>(
this IEnumerable<T> source,
Func<T, DateTime> startDateSelector,
Func<T, DateTime> expiryDateSelector,
TimeSpan maxTime)
{
return source.Where(t => t.IsWithinTimeSpan(
startDateSelector, expiryDateSelector, maxTime));
}
Well that was easy, only one line of code!
This looks very much like our goal, only one more function to go to make it like the method you want:
public static IEnumerable<PurchasedProduct> WhereAlmostExpired(
this IEnumerable<PurchasedProduct> purchasedProducts,
TimeSpan maxTime)
{
return purchasedProducts.WhereWithinTimeSpan(
product => product.PurchaseDate,
product => product.ExpiryDate,
maxTime);
}
Again, only one line of code! Of course, if your sequence of items is not IEnumerable<PurchasedProduct>, but for instance IEnumerable<MyClass>, change this one line of code accordingly.
So now we are able to use it for your problem:
TimeSpan maxTime = TimeSpan.FromDays(45);
IEnumerable<MyClass> myObjects = ...
IEnumerable<MyClass> almostExpiredObjects = myObjects.WhereAlmostExpired(maxTime);
Simple comme bonjour!
One final remark: if you are not certain that startTime is smaller then endTime, don't forget to use absolute value before your comparison

Seeding many-to-many databases in EFCore5 with ModelBuilder?

There are many questions about seeding many-to-many relationships in Entity Framework. However, most of them are extremely old, and many-to-many behavior has changed significantly in EFCore5. The official docs recommend overriding OnModelCreating to implement ModelBuilder.Entity<>.HasData().
However, with the new many-to-many behavior (without explicit mappings), I can find no clear path to seed the intermediate tables. To use the example of this tutorial, the BookCategories class is now implicit. Therefore, there is no path to explicitly declare the intermediate table values while seeding.
I've also tried simply assigning the arrays, e.g.,:
public class Book
{
public int BookId { get; set; }
public string Title { get; set; }
public ICollection<Category> Categories { get; set; }
}
public class Category
{
public int CategoryId { get; set; }
public string CategoryName { get; set; }
public ICollection<Book> Books { get; set; }
}
And then at seed time:
Book book = new Book() { BookId = 1, Title = "Brave New World" }
Category category = new Category() { CategoryId = 1, CategoryName = "Dystopian" }
category.Books = new List<Book>() { book };
book.Categories = new List<Category>() { category };
modelBuilder.Entity<Book>().HasData(book);
modelBuilder.Entity<Category>().HasData(category);
... but there are no entries created for BookCategories in the resulting migration. This was somewhat expected, as this article suggests that one must explicitly seed the intermediate table. What I want is something like this:
modelBuilder.Entity<BookCategory>().HasData(
new BookCategory() { BookId = 1, CategoryId = 1 }
);
However, again, since there is no concrete class to describe BookCategories in EFCore5, the only way I can think of to seed the table is to manually edit the migration with additional MigrationBuilder.InsertData commands, which rather defeats the purpose of seeding data via application code.
However, again, since there is no concrete class to describe BookCategories in EFCore5
Actually, as explained in the What's new link, EF Core 5 allows you to have explicit join entity
public class BookCategory
{
public int BookId { get; set; }
public EBook Book { get; set; }
public int CategoryId { get; set; }
public Category Category { get; set; }
}
and configure the many-to-many relationship to use it
modelBuilder.Entity<Book>()
.HasMany(left => left.Categories)
.WithMany(right => right.Books)
.UsingEntity<BookCategory>(
right => right.HasOne(e => e.Category).WithMany(),
left => left.HasOne(e => e.Book).WithMany().HasForeignKey(e => e.BookId),
join => join.ToTable("BookCategories")
);
This way you can use all normal entity operations (query, change tracking, data model seeding etc.) with it
modelBuilder.Entity<BookCategory>().HasData(
new BookCategory() { BookId = 1, CategoryId = 1 }
);
still having the new many-to-many skip navigations mapping.
This is probably the simplest as well as the type-safe approach.
In case you thing it's too much, using the conventional join entity is also possible, but you need to know the shared dictionary entity type name, as well as the two shadow property names. Which as you will see by convention might not be what you expect.
So, by convention the join entity (and table) name is
{LeftEntityName}{RightEntityName}
and the shadow property (and column) names are
{LeftEntityNavigationPropertyName}{RightEntityKeyName}
{RightEntityNavigationPropertyName}{LeftEntityKeyName}
The first question would be - which is the left/right entity? The answer is (not documented yet) - by convention the left entity is the one which name is less in alphabetical order. So with your example Book is left, Category is right, so the join entity and table name would be BookCategory.
It can be changed adding explicit
modelBuilder.Entity<Category>()
.HasMany(left => left.Books)
.WithMany(right => right.Categories);
and now it would be CategoryBook.
In both cases the shadow property (and column) names would be
CategoriesCategoryId
BooksBookId
So neither the table name, nor the property/column names are what you'd normally do.
And apart from the database table/column names, the entity and property names are important because you'd need them for entity operations, including the data seeding in question.
With that being said, even if you don't create explicit join entity, it's better to configure fluently the one created automatically by EF Core convention:
modelBuilder.Entity<Book>()
.HasMany(left => left.Categories)
.WithMany(right => right.Books)
.UsingEntity("BookCategory", typeof(Dictionary<string, object>),
right => right.HasOne(typeof(Category)).WithMany().HasForeignKey("CategoryId"),
left => left.HasOne(typeof(Book)).WithMany().HasForeignKey("BookId"),
join => join.ToTable("BookCategories")
);
Now you can use the entity name to access the EntityTypeBuilder
modelBuilder.Entity("BookCategories")
and you can seed it similar to normal entities with shadow FK properties with anonymous type
modelBuilder.Entity("BookCategory").HasData(
new { BookId = 1, CategoryId = 1 }
);
or for this specific property bag type entity, also with Dictionary<string, object> instances
modelBuilder.Entity("BookCategory").HasData(
new Dictionary<string, object> { ["BookId"] = 1, ["CategoryId"] = 1 }
);
Update:
People seem to misinterpret the aforementioned "extra" steps and find them redundant and "too much", not needed.
I never said they are mandatory. If you know the conventional join entity and property names, go ahead directly to the last step and use anonymous type or Dictionary<string, object>.
I already explained the drawbacks of taking that route - loosing the C# type safety and using "magic" strings out of your control. You have to be smart enough to know the exact EF Core naming conventions and to realize that if you rename class Book to EBook the new join entity/table name will change from "BookCategory" to "CategoryEBook" as well as the order of the PK properties/columns, associated indexes etc.
Regarding the concrete problem with data seeding. If you really want to generalize it (OP attempt in their own answer), at least make it correctly by using the EF Core metadata system rather than reflection and assumptions. For instance, the following will extract these names from the EF Core metadata:
public static void HasJoinData<TFirst, TSecond>(
this ModelBuilder modelBuilder,
params (TFirst First, TSecond Second)[] data)
where TFirst : class where TSecond : class
=> modelBuilder.HasJoinData(data.AsEnumerable());
public static void HasJoinData<TFirst, TSecond>(
this ModelBuilder modelBuilder,
IEnumerable<(TFirst First, TSecond Second)> data)
where TFirst : class where TSecond : class
{
var firstEntityType = modelBuilder.Model.FindEntityType(typeof(TFirst));
var secondEntityType = modelBuilder.Model.FindEntityType(typeof(TSecond));
var firstToSecond = firstEntityType.GetSkipNavigations()
.Single(n => n.TargetEntityType == secondEntityType);
var joinEntityType = firstToSecond.JoinEntityType;
var firstProperty = firstToSecond.ForeignKey.Properties.Single();
var secondProperty = firstToSecond.Inverse.ForeignKey.Properties.Single();
var firstValueGetter = firstToSecond.ForeignKey.PrincipalKey.Properties.Single().GetGetter();
var secondValueGetter = firstToSecond.Inverse.ForeignKey.PrincipalKey.Properties.Single().GetGetter();
var seedData = data.Select(e => (object)new Dictionary<string, object>
{
[firstProperty.Name] = firstValueGetter.GetClrValue(e.First),
[secondProperty.Name] = secondValueGetter.GetClrValue(e.Second),
});
modelBuilder.Entity(joinEntityType.Name).HasData(seedData);
}
Also here you don't need to know which type is "left" and which is "right", neither requires special base class or interface. Just pass sequence of entity pairs and it will properly seed the conventional join entity, e.g. with OP example, both
modelBuilder.HasJoinData((book, category));
and
modelBuilder.HasJoinData((category, book));
would do.
Update (EF Core 5.0.2)
It's working well using the name of the associative table:
builder.Entity("ContractDeclarationType").HasData(
new { ContractsId = 1L, DeclarationTypesId = 1L },
new { ContractsId = 1L, DeclarationTypesId = 2L },
new { ContractsId = 1L, DeclarationTypesId = 3L });
I ended up whipping up a generic solution to this problem based upon the answer from Ivan (thanks!). I'm now able to seed all my M2M tables with this syntax:
// Add book1 and book2 to category1:
modelBuilder.HasM2MData(new [] { book1, book2 }, new [] { category1 });
This may not be fully robust, but it should work with conventional M2M mappings.
It makes some assumptions:
T1 & T2 Inherit from some ModelBase that provides an Id property.
T1 & T2 Have exactly one ICollection<OtherType> property.
You know the correct order (which model is T1 and which is T2) — this can be discovered by running the migration for the tables first and inspecting the migration.
You're running EFCore5 RC2 or later (see this issue).
public static void HasM2MData<T1, T2>
(this ModelBuilder mb, T1[] t1s, T2[] t2s)
where T1 : ModelBase where T2 : ModelBase
{
string table = $"{typeof(T1).Name}{typeof(T2).Name}";
PropertyInfo t1Prop = GetM2MProperty<T1, T2>();
PropertyInfo t2Prop = GetM2MProperty<T2, T1>();
string t1Key = $"{t1Prop.Name}Id";
string t2Key = $"{t2Prop.Name}Id";
foreach (T1 t1 in t1s) {
foreach (T2 t2 in t2s) {
mb.Entity(table).HasData(new Dictionary<string, object>() { [t2Key] = t1.Id, [t1Key] = t2.Id });
}
}
}
// Get a property on T1 which is assignable to type ICollection<T2>, representing the m2m relationship
private static PropertyInfo GetM2MProperty<T1, T2>() {
Type assignableType = typeof(ICollection<T2>);
List<PropertyInfo> props = typeof(T1).GetProperties()
.Where(pi => pi.PropertyType.IsAssignableTo(assignableType))
.ToList();
if (props.Count() != 1) {
throw new SystemException(
$"Expected {typeof(T1)} to have exactly one column of type {assignableType}; got: {props.Count()}");
}
return props.First();
}
In the migration, we see something like:
migrationBuilder.InsertData(
table: "BookCategory",
columns: new[] { "BooksId", "CategoriesId" },
values: new object[,]
{
{ "book1", "category1" },
{ "book2", "category1" }
});

How to use JsonConvert.SerializeObject with formatting to add brackets only around CSV values

I have an object that, when converted to a JSON string using the JsonConvert.SerializeObject method, will look like this:
{"01":{"CompanyName":"Hertz","Cars":"Ford, BMW, Fiat"},
"02":{"CompanyName":"Avis","Cars":"Dodge, Nash, Buick"}}
How can I use the Formatting parameter to make the result look like this:
{"01":{"CompanyName":"Hertz","Cars":["Ford", "BMW", "Fiat"]},
"02":{"CompanyName":"Avis","Cars":["Dodge", "Nash", "Buick"]}}
As #dbc mentioned in the comments, you cannot use the Formatting parameter of JsonConvert.SerializeObject to affect whether a particular value in the JSON is surrounded by square brackets or not. The Formatting parameter only controls whether or not Json.Net will add indenting and line breaks to the JSON output to make it easier to read by a human.
In JSON, square brackets are used to denote an array of values, as opposed to a single value. So, if you want to add square brackets for a particular property, the easiest way to do that is to change how that property is declared in your class such that it correspondingly represents an array (or list).
Based on your original JSON, I'm assuming you have a class which looks like this:
public class Company
{
public string CompanyName { get; set; }
public string Cars { get; set; }
}
...and you are creating your JSON something like this:
var results = new Dictionary<string, Company>();
results.Add("01", new Company
{
CompanyName = "Hertz",
Cars = "Ford, BMW, Fiat"
});
results.Add("02", new Company
{
CompanyName = "Avis",
Cars = "Dodge, Nash, Buick"
});
string json = JsonConvert.SerializeObject(results);
To get square brackets in the JSON, change the type of your Cars property from string to List<string>:
public class Company
{
public string CompanyName { get; set; }
public List<string> Cars { get; set; }
}
Of course, you will also need to make a corresponding change to the code which populates the results:
var results = new Dictionary<string, Company>();
results.Add("01", new Company
{
CompanyName = "Hertz",
Cars = new List<string> { "Ford", "BMW", "Fiat" }
});
results.Add("02", new Company
{
CompanyName = "Avis",
Cars = new List<string> { "Dodge", "Nash", "Buick" }
});
string json = JsonConvert.SerializeObject(results);
Here is a short demo: https://dotnetfiddle.net/lgg9jk

RavenDB query by index and DateTime

I'm quite new to RavenDB so sorry if my question sounds stupid. I have a class which contains a DateTime property. I store instances of this class in RavenDB. I have defined index the following way:
from doc in docs.Orders
from docItemsItem in ((IEnumerable<dynamic>)doc.Items).DefaultIfEmpty()
select new { Items_Price_Amount = docItemsItem.Price.Amount, Items_Quantity = docItemsItem.Quantity, Date = doc.Date }
http://dl.dropbox.com/u/3055964/Capture.GIF <-- here's a screenshot
Here's class definition:
public class Order
{
public DateTime Date { get; set; }
public IList<OrderItem> Items { get; set; }
public string CustomerId { get; set; }
public Order()
{
Items = new List<OrderItem>();
}
}
Now, when I try to query RavenDB with the index shown above, the query yields no result at all.
var orders = session.Query<Order>("OrdersIndex").Where(o => o.Date > DateTime.Now).ToList(); // orders.Count == 0
If I omit the index from query, like this:
var orders = session.Query<Order>().Where(o => o.Date > DateTime.Now).ToList(); // orders.Count == 128
a temporary index is created and eveything works as expected.
Does anyone has any idea what's wrong with my query?
Thanks.
UPDATE
Allright, I removed Fields Date, Items,Price,Amount and Items,Quantity via management studio (shown in screenshot), and now the query works fine. Anyone any idea why? What's the purpose to define those fields explicitly?
Check that the date in the Index is stored as Index(x => x.Date, FieldIndexing.Default).
I had it set to FieldIndexing.Analysed, and wasn't getting the correct results back.
I need to read up more on the difference between the different FieldIndexing options :)

Resources