This question is unlikely to help any future visitors; it is only relevant to a small geographic area, a specific moment in time, or an extraordinarily narrow situation that is not generally applicable to the worldwide audience of the internet. For help making this question more broadly applicable, visit the help center.
Closed 10 years ago.
I'm having some trouble with date formats in indexes. They're
serializing to something indeserializable. Our entities have this
shape:
[Serializable]
public class Publication
{
public Guid? Id { get; set; }
public PublicationRendering Rendering { get; protected internal set; }
public DateRange SuggestedActiveRange { get; protected set; }
public DateRange ActualActiveRange { get; protected internal set; }
...
}
public class DateRange
{
public DateTime StartDate { get; private set; }
public DateTime? EndDate { get; set; }
...
}
The document is serialized properly:
publications/806059ce-fd7a-4655-8e0e-9fff00f5ebd3
{
...
"SuggestedActiveRange": {
"StartDate": "2011-11-22T00:00:00.0000000Z",
"EndDate": "2012-01-22T00:00:00.0000000Z",
"TimeSpan": "61.00:00:00"
},
"ActualActiveRange": {
"StartDate": "2011-11-22T00:00:00.0000000Z",
"EndDate": "2012-01-22T00:00:00.0000000Z",
"TimeSpan": "61.00:00:00"
},
...
}
And I'm defining my index as such (it's a multi-reduce):
public class PublishedPolicyIndex :
AbstractMultiMapIndexCreationTask<PublishedPolicyIndex.ReduceResult>
{
public PublishedPolicyIndex() {
AddMap<Publication>(publications => publications.Select(publication => new {
ArtifactId = "artifacts/" + publication.Rendering.ArtifactId,
ActiveStartDate = publication.ActualActiveRange.StartDate,
ActiveEndDate = publication.ActualActiveRange.EndDate,
ViewingPrincipals = (string[]) null,
...
}));
AddMap<Artifact>(artifacts => artifacts.Select(artifact => new {
ArtifactId = artifact.Id,
ActiveStartDate = (string) null,
ActiveEndDate = (string) null,
artifact.ViewingPrincipals,
...
}));
Reduce = results => results.GroupBy(result => result.ArtifactId).Select(g => new {
ArtifactId = g.Key,
ActiveStartDate = g.Select(x => x.ActiveStartDate).SingleOrDefault(x => x != null),
ActiveEndDate = g.Select(x => x.ActiveEndDate).SingleOrDefault(x => x != null),
ViewingPrincipals = g.Select(x => x.ViewingPrincipals).SingleOrDefault(x => x != null),
...
});
Analyzers = new Dictionary<Expression<Func<ReduceResult, object>>, string> {
{rr => rr.ActiveStartDate, "Lucene.Net.Analysis.Standard.StandardAnalyzer"},
{rr => rr.ActiveEndDate, "Lucene.Net.Analysis.Standard.StandardAnalyzer"},
...
};
Stores.Add(x => x.ActiveStartDate, FieldStorage.Yes);
Stores.Add(x => x.ActiveEndDate, FieldStorage.Yes);
}
public class ReduceResult : IReduceResults
{
public string ArtifactId { get; set; }
public string ActiveStartDate { get; set; }
public string ActiveEndDate { get; set; }
public string[] ViewingPrincipals { get; set; }
...
}
}
But when I look in my index I have this data:
{
"ArtifactId": "artifacts/533b8cba-8b8f-4c23-b89a-9fff00f5ebd3",
"ActiveStartDate": "20111122000000000",
"ActiveEndDate": "20120322000000000",
"ViewingPrincipals": [
"b0202923-eb07-493d-a0b5-9fff00f5ebd3"
],
...
}
It's almost as if it were hashing these dates. Maybe I didn't setup
my field store correctly? If I explicitly call .ToString("u"), it
will store the dates in a format that can be deserialized, but not
quite equal to the format I want, plus that's too messy.
Related
JSON Output
{
"balance":100.0,
"trc10": [{
"TR7NHqjeK": "10000000",
"KQxGTCi8": "20000000"
}],
"trc20": [{
"TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t": "10000000",
"TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjL56": "40000000"
}]
}
public class Root
{
public double balance { get; set; }
public List<dynamic> trc10 { get; set; }
public List<dynamic> trc20 { get; set; }
}
The code to transform the JSON would look something like this:
c# code
Root myDeserializedClass = JsonConvert.DeserializeObject<Root>(myJsonResponse);
Response.Write((myDeserializedClass.balance).ToString());
myDeserializedClass.balance output - 100.0
how to gat value of trc10,trc20 List item with select and where query
like myDeserializedClass.trc20.Where(x => x.TR7NHqjeKQxGTCi8q8ZY4pL8otSsssj6t == "TR7NHqjeKQxGTCi8q8ZY4pL8otSsssj6t")
I have a Search component that implements a debounce timer so it doesn't call ValueChanged (and therefore doesn't update the property tied to it immediately).
My Issue
The bUnit test doesn't appear to two way bind my value I am updating.
Test code
private string StringProperty { get; set; }
[Fact]
public async Task AfterDebounce_ValueUpdates()
{
var myString = "";
var cut = RenderComponent<Search>(parameters => parameters
.Add(p => p.Value, StringProperty)
.Add(p => p.ValueChanged, (s) => myString = s)
);
var input = cut.Find("input");
input.Input("unit test");
Assert.Equal("unit test", cut.Instance.Value);
Assert.NotEqual("unit test", myString);
//Assert.NotEqual("unit test", StringProperty);
await Task.Delay(5000);
Assert.Equal("unit test", myString);
//Assert.Equal("unit test", StringProperty);
}
I would have expected the commented out parts to work (as they are doing the same thing as the ValueChanged to update the property), but they fail.
The component
public class Search : ComponentBase
{
[Parameter] public string? Value { get; set; }
[Parameter] public EventCallback<string> ValueChanged { get; set; }
[DisallowNull] public ElementReference? Element { get; protected set; }
private System.Timers.Timer timer = null;
protected string? CurrentValue {
get => Value;
set {
var hasChanged = !EqualityComparer<string>.Default.Equals(value, Value);
if (hasChanged)
{
Value = value;
DisposeTimer();
timer = new System.Timers.Timer(350);
timer.Elapsed += TimerElapsed_TickAsync;
timer.Enabled = true;
timer.Start();
}
}
}
private void DisposeTimer()
{
if (timer != null)
{
timer.Enabled = false;
timer.Elapsed -= TimerElapsed_TickAsync;
timer.Dispose();
timer = null;
}
}
private async void TimerElapsed_TickAsync(
object sender,
EventArgs e)
{
await ValueChanged.InvokeAsync(Value);
}
protected override void BuildRenderTree(RenderTreeBuilder builder)
{
builder.OpenElement(10, "input");
builder.AddAttribute(20, "type", "text");
builder.AddAttribute(60, "value", BindConverter.FormatValue(CurrentValue));
builder.AddAttribute(70, "oninput", EventCallback.Factory.CreateBinder<string?>(this, __value => CurrentValue = __value, CurrentValue));
builder.AddElementReferenceCapture(80, __inputReference => Element = __inputReference);
builder.CloseElement();
}
}
How it is used:
It may be used like this where the grid will update whenever Query is updated.
<Search #bind-Value=Query />
<Grid Query=#Query />
#code {
private string? Query { get; set; }
}
This works fine in practice, but when testing I am having issues.
I tried locally on my machine, and the test passed.
Here is a simplified version of your component, that only calls TimerElapsed_TickAsync one time per value change and not every time the timer runs out (AutoReset defaults to true), and two different ways to write the test that both pass on my machine:
public class Search : ComponentBase, IDisposable
{
private readonly Timer timer;
[Parameter] public string? Value { get; set; }
[Parameter] public EventCallback<string> ValueChanged { get; set; }
[DisallowNull] public ElementReference? Element { get; protected set; }
public Search()
{
timer = new Timer(350);
timer.Elapsed += TimerElapsed_TickAsync;
timer.Enabled = true;
timer.AutoReset = false;
}
protected string? CurrentValue
{
get => Value;
set
{
var hasChanged = !EqualityComparer<string>.Default.Equals(value, Value);
if (hasChanged)
{
RestartTimer();
Value = value;
}
}
}
private void RestartTimer()
{
if (timer.Enabled)
timer.Stop();
timer.Start();
}
private void TimerElapsed_TickAsync(object sender, EventArgs e)
=> ValueChanged.InvokeAsync(Value);
protected override void BuildRenderTree(RenderTreeBuilder builder)
{
builder.OpenElement(10, "input");
builder.AddAttribute(20, "type", "text");
builder.AddAttribute(60, "value", BindConverter.FormatValue(CurrentValue));
builder.AddAttribute(70, "oninput", EventCallback.Factory.CreateBinder<string?>(this, __value => CurrentValue = __value, CurrentValue));
builder.AddElementReferenceCapture(80, __inputReference => Element = __inputReference);
builder.CloseElement();
}
public void Dispose() => timer.Dispose();
}
And the C# version of the test:
[Fact]
public async Task AfterDebounce_ValueUpdates()
{
var expected = "test input";
var count = 0;
var value = "";
var cut = RenderComponent<Search>(parameters => parameters
.Add(p => p.Value, value)
.Add(p => p.ValueChanged, (s) =>
{
value = s;
count++;
})
);
cut.Find("input").Input(expected);
await Task.Delay(350);
Assert.Equal(1, count);
Assert.Equal(expected, value);
}
and the .razor version of the test (aka. written in a .razor file):
#inherits TestContext
#code
{
[Fact]
public async Task AfterDebounce_ValueUpdates()
{
var expected = "test input";
var value = "";
var cut = Render(#<Search #bind-Value="value" /> );
cut.Find("input").Input(expected);
await Task.Delay(350);
Assert.Equal(expected, value);
}
}
I have sealed a class with no constructor which is I am referred using SDK to my project. I want to create fixture data for the class to write test but AutoFixture is giving an expectation like below.
AutoFixture was unable to create an instance from SealedTypeclass, most likely because it has no public constructor, is an abstract or non-public type.
Please find the below code example for which I am trying to create a fixture.
public sealed class TokenCacheItem
{
public string Authority { get; }
public string ClientId { get; }
public DateTimeOffset ExpiresOn { get; }
public string FamilyName { get; }
public string GivenName { get; }
public string IdentityProvider { get; }
public string TenantId { get; }
}
With the above-sealed class i am referring through SDK and I am trying to create fixture data. I am getting the below error message.
Message:
AutoFixture.ObjectCreationExceptionWithPath : AutoFixture was unable to create an instance from ***, most likely because it has no public constructor, is an abstract or non-public type.
Any generic solution?
Given that it's sealed and reporting that it doesn't have a public constructor, you're going to have to provide a way to create an instance and it's probably going to be a reflection based solution. The read only properties add another complexity for AutoFixture as well.
Without seeing the constructor, or whether there are any backing fields for the read only properties I'm going to make some assumptions with the following working example.
Create something that can create a TokenCacheItem and set its properties:
public class MutableTokenCacheItem
{
private TokenCacheItem _tokenCacheItem;
public string Authority { get => _tokenCacheItem.Authority; set => SetPropertyValue(x => x.Authority, value); }
public string ClientId { get => _tokenCacheItem.ClientId; set => SetPropertyValue(x => x.ClientId, value); }
public DateTimeOffset ExpiresOn { get => _tokenCacheItem.ExpiresOn; set => SetPropertyValue(x => x.ExpiresOn, value); }
public string FamilyName { get => _tokenCacheItem.FamilyName; set => SetPropertyValue(x => x.FamilyName, value); }
public string GivenName { get => _tokenCacheItem.GivenName; set => SetPropertyValue(x => x.GivenName, value); }
public string IdentityProvider { get => _tokenCacheItem.IdentityProvider; set => SetPropertyValue(x => x.IdentityProvider, value); }
public string TenantId { get => _tokenCacheItem.TenantId; set => SetPropertyValue(x => x.TenantId, value); }
public MutableTokenCacheItem()
{
var ctor = typeof(TokenCacheItem).GetConstructors(BindingFlags.Instance | BindingFlags.NonPublic).Single();
_tokenCacheItem = (TokenCacheItem)ctor.Invoke(null);
}
private void SetPropertyValue<P>(Expression<Func<TokenCacheItem, P>> expression, object value)
{
var body = expression.Body as MemberExpression;
var backingField = typeof(TokenCacheItem).GetRuntimeFields().Where(a => Regex.IsMatch(a.Name, $"\\A<{body.Member.Name}>k__BackingField\\Z")).Single();
backingField.SetValue(_tokenCacheItem, value);
}
public TokenCacheItem AsImmutableTokenCacheItem()
{
return _tokenCacheItem;
}
}
Create a specimen builder to bolt it into AutoFixture nicely:
public class TokenCacheItemSpecimenBuilder : ISpecimenBuilder
{
public object Create(object request, ISpecimenContext context)
{
var t = request as Type;
if (typeof(TokenCacheItem).Equals(t))
{
var mutableTokenCacheItem = context.Create<MutableTokenCacheItem>();
return mutableTokenCacheItem.AsImmutableTokenCacheItem();
}
return new NoSpecimen();
}
}
Add the customization and off you go:
var fixture = new Fixture();
fixture.Customizations.Add(new TokenCacheItemSpecimenBuilder());
fixture.Create<TokenCacheItem>();
Working LINQPad example:
void Main()
{
var fixture = new Fixture();
fixture.Customizations.Add(new TokenCacheItemSpecimenBuilder());
Console.Write(fixture.Create<TokenCacheItem>());
}
public class TokenCacheItemSpecimenBuilder : ISpecimenBuilder
{
public object Create(object request, ISpecimenContext context)
{
var t = request as Type;
if (typeof(TokenCacheItem).Equals(t))
{
var mutableTokenCacheItem = context.Create<MutableTokenCacheItem>();
return mutableTokenCacheItem.AsImmutableTokenCacheItem();
}
return new NoSpecimen();
}
}
public class MutableTokenCacheItem
{
private TokenCacheItem _tokenCacheItem;
public string Authority { get => _tokenCacheItem.Authority; set => SetPropertyValue(x => x.Authority, value); }
public string ClientId { get => _tokenCacheItem.ClientId; set => SetPropertyValue(x => x.ClientId, value); }
public DateTimeOffset ExpiresOn { get => _tokenCacheItem.ExpiresOn; set => SetPropertyValue(x => x.ExpiresOn, value); }
public string FamilyName { get => _tokenCacheItem.FamilyName; set => SetPropertyValue(x => x.FamilyName, value); }
public string GivenName { get => _tokenCacheItem.GivenName; set => SetPropertyValue(x => x.GivenName, value); }
public string IdentityProvider { get => _tokenCacheItem.IdentityProvider; set => SetPropertyValue(x => x.IdentityProvider, value); }
public string TenantId { get => _tokenCacheItem.TenantId; set => SetPropertyValue(x => x.TenantId, value); }
public MutableTokenCacheItem()
{
var ctor = typeof(TokenCacheItem).GetConstructors(BindingFlags.Instance | BindingFlags.NonPublic).Single();
_tokenCacheItem = (TokenCacheItem)ctor.Invoke(null);
}
private void SetPropertyValue<P>(Expression<Func<TokenCacheItem, P>> expression, object value)
{
var body = expression.Body as MemberExpression;
var backingField = typeof(TokenCacheItem).GetRuntimeFields().Where(a => Regex.IsMatch(a.Name, $"\\A<{body.Member.Name}>k__BackingField\\Z")).Single();
backingField.SetValue(_tokenCacheItem, value);
}
public TokenCacheItem AsImmutableTokenCacheItem()
{
return _tokenCacheItem;
}
}
public sealed class TokenCacheItem
{
public string Authority { get; }
public string ClientId { get; }
public DateTimeOffset ExpiresOn { get; }
public string FamilyName { get; }
public string GivenName { get; }
public string IdentityProvider { get; }
public string TenantId { get; }
private TokenCacheItem() { }
}
Result:
YMMV depending on the actual TokenCacheItem implementation though it's probably not far off.
I have a method in my repository that I’m trying to test
public User UpdateUserManyToMany(User user, List<Guid> manyToManyds)
{
var dbContext = _databaseContext as DbContext;
dbContext?.TryUpdateManyToMany(user.ManyToMany, manyToManyds
.Select(x => new ManyToMany{
OtherEntityId = x,
UserId = user.Id,
}), x => x.OtherEntityId);
return user;
}
My ManyToMany Entity :
public class ManyToMany
{
public Guid OtherEntityId { get; set; }
public OtherEntity OtherEntityId { get; set; }
public Guid UserId { get; set; }
public User User { get; set; }
}
My TryUpdateManyToMany :
public static class ManyToManyExtensions
{
public static void TryUpdateManyToMany<T, TKey>(this DbContext db, IEnumerable<T> currentItems, IEnumerable<T> newItems, Func<T, TKey> getKey) where T : class
{
db.Set<T>().RemoveRange(currentItems.Except(newItems, getKey));
db.Set<T>().AddRange(newItems.Except(currentItems, getKey));
}
public static IEnumerable<T> Except<T, TKey>(this IEnumerable<T> items, IEnumerable<T> other, Func<T, TKey> getKeyFunc)
{
return items
.GroupJoin(other, getKeyFunc, getKeyFunc, (item, tempItems) => new { item, tempItems })
.SelectMany(t => t.tempItems.DefaultIfEmpty(), (t, temp) => new { t, temp })
.Where(t => ReferenceEquals(null, t.temp) || t.temp.Equals(default(T)))
.Select(t => t.t.item);
}
}
Here’s my unit test :
using (var context = new InMemoryDataBaseContext())
{
// Arrange
var repository = new UserRepository(context);
await context.Users.AddRangeAsync(GetUser());
await context.SaveChangesAsync();
// Act
var manyIds = new List<Guid>();
manyIds.Add(Guid.Parse("855d1a64-a707-40d5-ab93-34591a923abf"));
manyIds.Add(Guid.Parse("855d1a64-a787-40d9-ac93-34591a923abf"));
manyIds.Add(Guid.Parse("855d1a64-a707-41d9-ab93-39591a923abf"));
var user = new User();
var expected = repository.UpdateUserManyToMany(GetUser(), manyIds);
// Assert
}
But I get the following error in my test :
Message:
System.InvalidOperationException : The instance of entity type 'ManyToMany' cannot be tracked because another instance with the same key value for {'UserId', 'OtherEntityId'} is already being tracked. When attaching existing entities, ensure that only one entity instance with a given key value is attached. Consider using 'DbContextOptionsBuilder.EnableSensitiveDataLogging' to see the conflicting key values.
Arborescence des appels de procédure:
IdentityMap`1.ThrowIdentityConflict(InternalEntityEntry entry)
IdentityMap`1.Add(TKey key, InternalEntityEntry entry, Boolean updateDuplicate)
IdentityMap`1.Add(TKey key, InternalEntityEntry entry)
NullableKeyIdentityMap`1.Add(InternalEntityEntry entry)
StateManager.StartTracking(InternalEntityEntry entry)
InternalEntityEntry.SetEntityState(EntityState oldState, EntityState newState, Boolean acceptChanges, Boolean modifyProperties)
InternalEntityEntry.SetEntityState(EntityState entityState, Boolean acceptChanges, Boolean modifyProperties, Nullable`1 forceStateWhenUnknownKey)
EntityGraphAttacher.PaintAction(EntityEntryGraphNode`1 node)
EntityEntryGraphIterator.TraverseGraph[TState](EntityEntryGraphNode`1 node, Func`2 handleNode)
EntityGraphAttacher.AttachGraph(InternalEntityEntry rootEntry, EntityState targetState, EntityState storeGeneratedWithKeySetTargetState, Boolean forceStateWhenUnknownKey)
DbContext.SetEntityState(InternalEntityEntry entry, EntityState entityState)
DbContext.RemoveRange(IEnumerable`1 entities)
InternalDbSet`1.RemoveRange(IEnumerable`1 entities)
ManyToManyExtensions.TryUpdateManyToMany[T,TKey](DbContext db, IEnumerable`1 currentItems, IEnumerable`1 newItems, Func`2 getKey) ligne 24
UserRepository.UpdateUserManyToMany(User user, List`1 manyToManyds) ligne 59
MyRepoUnitTest.MyTestMethod() ligne 102
--- End of stack trace from previous location where exception was thrown ```
The following sample program, that is based on the code you provided, works without issues:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;
namespace IssueConsoleTemplate
{
public class User
{
public Guid Id { get; set; }
public string Name { get; set; }
public ICollection<ManyToMany> ManyToMany { get; set; } = new HashSet<ManyToMany>();
}
public class OtherEntity
{
public Guid Id { get; set; }
public string Name { get; set; }
public ICollection<ManyToMany> ManyToMany { get; set; } = new HashSet<ManyToMany>();
}
public class ManyToMany
{
public Guid OtherEntityId { get; set; }
public Guid UserId { get; set; }
public OtherEntity OtherEntity { get; set; }
public User User { get; set; }
}
public class Context : DbContext
{
public DbSet<OtherEntity> OtherEntities { get; set; }
public DbSet<User> Users { get; set; }
public DbSet<ManyToMany> ManyToMany { get; set; }
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder
.UseSqlServer(#"Data Source=.\MSSQL14;Integrated Security=SSPI;Initial Catalog=So63077461")
.UseLoggerFactory(
LoggerFactory.Create(
b => b
.AddConsole()
.AddFilter(level => level >= LogLevel.Information)))
.EnableSensitiveDataLogging()
.EnableDetailedErrors();
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<OtherEntity>(
entity =>
{
entity.HasKey(e => e.Id);
entity.HasMany(e => e.ManyToMany)
.WithOne(e => e.OtherEntity)
.HasForeignKey(e => e.OtherEntityId);
entity.HasData(
new OtherEntity
{
Id = new Guid("855d1a64-a707-40d5-ab93-34591a923abf"),
Name = "Bicycle"
},
new OtherEntity
{
Id = new Guid("855d1a64-a787-40d9-ac93-34591a923abf"),
Name = "Bus"
},
new OtherEntity
{
Id = new Guid("855d1a64-a707-41d9-ab93-39591a923abf"),
Name = "Plane"
});
});
modelBuilder.Entity<User>(
entity =>
{
entity.HasKey(e => e.Id);
entity.HasMany(e => e.ManyToMany)
.WithOne(e => e.User)
.HasForeignKey(e => e.UserId);
});
modelBuilder.Entity<ManyToMany>(
entity =>
{
entity.HasKey(e => new {e.OtherEntityId, e.UserId});
});
}
}
public static class ManyToManyExtensions
{
public static void TryUpdateManyToMany<T, TKey>(this DbContext db, IEnumerable<T> currentItems, IEnumerable<T> newItems, Func<T, TKey> getKey) where T : class
{
db.Set<T>().RemoveRange(currentItems.Except(newItems, getKey));
db.Set<T>().AddRange(newItems.Except(currentItems, getKey));
}
public static IEnumerable<T> Except<T, TKey>(this IEnumerable<T> items, IEnumerable<T> other, Func<T, TKey> getKeyFunc)
{
return items
.GroupJoin(other, getKeyFunc, getKeyFunc, (item, tempItems) => new { item, tempItems })
.SelectMany(t => t.tempItems.DefaultIfEmpty(), (t, temp) => new { t, temp })
.Where(t => ReferenceEquals(null, t.temp) || t.temp.Equals(default(T)))
.Select(t => t.t.item);
}
}
internal class UserRepository
{
private readonly Context _databaseContext;
public UserRepository(Context context)
{
_databaseContext = context;
}
public User UpdateUserManyToMany(User user, List<Guid> manyToManyds)
{
var dbContext = _databaseContext as DbContext;
dbContext?.TryUpdateManyToMany(user.ManyToMany, manyToManyds
.Select(x => new ManyToMany{
OtherEntityId = x,
UserId = user.Id,
}), x => x.OtherEntityId);
return user;
}
}
internal static class Program
{
private static async Task Main()
{
//
// Operations with referential integrity intact:
//
using var context = new Context();
context.Database.EnsureDeleted();
context.Database.EnsureCreated();
// Arrange
var repository = new UserRepository(context);
await context.Users.AddRangeAsync(GetUser());
await context.SaveChangesAsync();
// Act
var manyIds = new List<Guid>
{
new Guid("855d1a64-a707-40d5-ab93-34591a923abf"),
new Guid("855d1a64-a787-40d9-ac93-34591a923abf"),
new Guid("855d1a64-a707-41d9-ab93-39591a923abf")
};
var expected = repository.UpdateUserManyToMany(GetUser(), manyIds);
}
private static User GetUser()
=> User;
private static readonly User User = new User
{
Id = new Guid("30c35d2e-77fd-480b-9974-6ebf037a8f86"),
Name = "John"
};
}
}
System.InvalidOperationException : The instance of entity type 'ManyToMany' cannot be tracked because another instance with the same key value for {'UserId', 'OtherEntityId'} is already being tracked. When attaching existing entities, ensure that only one entity instance with a given key value is attached. Consider using 'DbContextOptionsBuilder.EnableSensitiveDataLogging' to see the conflicting key values.
The error message says, that at least one of your ManyToMany entries already exists in the database (there is an entry with the same UserId and OtherEntityId combination).
You can verify this, by running the following code directly after your filled the manyIds variable with the 3 IDs:
var user = GetUser();
var alreadyExistingManyToMany = context.ManyToMany
.Where(m => m.UserId == user.Id &&
manyIds.Contains(m.OtherEntityId))
.ToList();
Debug.Assert(alreadyExistingManyToMany.Count == 0);
This question is unlikely to help any future visitors; it is only relevant to a small geographic area, a specific moment in time, or an extraordinarily narrow situation that is not generally applicable to the worldwide audience of the internet. For help making this question more broadly applicable, visit the help center.
Closed 9 years ago.
Hope you can help me !!
I am collecting tweets, which have a created_at date (DataPublicacao), and some Hashtags. Each tweet refers to a broadcaster (redeId), and a show (programaId).
I want to query the database for the 20 most used hashtags in a certain period.
I have to map each hashtag, when it was used, and to which broadcaster and tv show it refers to.
Then, I need to be able to count the occurrences of each hashtag in a certain period (I dont know how).
public class Tweet : IModelo
{
public string Id { get; set; }
public string RedeId { get; set; }
public string ProgramaId { get; set; }
public DateTime DataPublicacao { get; set; }
public string Conteudo { get; set; }
public string Aplicacao { get; set; }
public Autor Autor { get; set; }
public Twitter.Monitor.Dominio.Modelo.TweetJson.Geo LocalizacaoGeo { get; set; }
public Twitter.Monitor.Dominio.Modelo.TweetJson.Place Localizacao { get; set; }
public Twitter.Monitor.Dominio.Modelo.TweetJson.Entities Entidades { get; set; }
public string Imagem { get; set; }
public Autor Para_Usuario { get; set; }
public string Retweet_Para_Status_Id { get; set; }
}
And the "entities" are hashtags, usermentions, and urls.
I tried to group the hashtags by broadcaster, tv show, and text, and listing the dates of the occurrences. Then, I have to transform the results, so I can count the occurrences on that period.
public class EntityResult
{
public string hashtagText { get; set; }
public string progId { get; set; }
public string redeId { get; set; }
public int listCount { get; set; }
}
public class HashtagsIndex : AbstractIndexCreationTask<Tweet, HashtagsIndex.ReduceResults>
{
public class ReduceResults
{
public string hashtagText { get; set; }
public DateTime createdAt { get; set; }
public string progId { get; set; }
public string redeId { get; set; }
public List<DateTime> datesList { get; set; }
}
public HashtagsIndex()
{
Map = tweets => from tweet in tweets
from hts in tweet.Entidades.hashtags
where tweet.Entidades != null
select new
{
createdAt = tweet.DataPublicacao,
progId = tweet.ProgramaId,
redeId = tweet.RedeId,
hashtagText = hts.text,
datesList = new List<DateTime>(new DateTime[] { tweet.DataPublicacao })
};
Reduce = results => from result in results
group result by new { result.progId, result.redeId, result.hashtagText }
into g
select new
{
createdAt = DateTime.MinValue,
progId = g.Key.progId,
redeId = g.Key.redeId,
hashtagText = g.Key.hashtagText,
datesList = g.ToList().Select(t => t.createdAt).ToList()
};
}
}
And the query I made so far is:
var hashtags2 = session.Query<dynamic, HashtagsIndex>().Customize(t => t.TransformResults((query, results) =>
results.Cast<dynamic>().Select(g =>
{
Expression<Func<DateTime, bool>> exp = o => o >= dtInit && o <= dtEnd;
int count = g.Where(exp);
return new EntityResult
{
redeId = g.redeId,
progId = g.progId,
hashtagText = g.hashtagText,
listCount = count
};
}))).Take(20).ToList();
Now I need to OrderByDescending(t=>t.count), so I cant Take(20) most used hashtags on that period.
How do I do that?
Is it possible to filter items before the mapreduce process?
A map/reduce index is just like any other index. All documents are processed through all indexes, always. So when phrased with "before" like you asked, the answer is clearly "no".
But I think you are just interested in filtering items during the indexing, and that is easily done in the map:
Map = items => from item in items
where item.foo == whatever // this is how you filter
select new
{
// whatever you want to map
}
This index will process all documents, but the resulting index will only contain items that match the filter you specified in the where clause.
Is it possible to subsequently group by features, like users by age, and then by region
Grouping is done in the reduce step. That is what map/reduce is all about.
My advice to you (and I mean no disrespect by this), is to walk before you try to run. Build a simple prototype or set of unit tests, and try first just basic storage and retrieval. Then try basic indexing and querying. Then try a simple map reduce, such as counting all your tweets. Only then should you attempt an advance map/reduce with other groupings. And if you run into trouble, then you will have code you can post here for help.
Is it possible?
Of course. Anything is possible. :)