Microsoft Moles : circular reference error? - unit-testing

I've the following Entity Framework entities:
public class Country
{
public long Id { get; set; }
public string Code { get; set; }
public virtual ICollection<Person> Persons { get; set; }
}
public class Person
{
public long Id { get; set; }
public long? Country_Id { get; set; }
public Country HomeCountry { get; set; }
}
Moles has generated MPerson and MCountry stub classes.
Now I do want to stub the set of the Country_Id:
MPerson.AllInstances.Country_IdSetNullableOfInt64 = (Person instance, long? id) =>
{
// Do something
// Set the Country_Id to the provided id
// This will trigger this same method again and again. How to avoid this ?
instance.Country_Id = id;
};

This post gives the answer:
MolesContext.ExecuteWithoutMoles(() => instance.Country_Id = id);

Related

EF Core Sort a list by related data

I implemented objects like below in ASP.NET Core 3.1:
public class Content: BaseModel
{
public int ContentId { get; set; }
public virtual List<ContentCBlock> ContentCBlocks { get; set; } = new List<ContentCBlock>();
}
public class CBlock : BaseModel
{
public int CBlockId { get; set; }
public virtual List<ContentCBlock> ContentCBlocks { get; set; } = new List<ContentCBlock>();
}
public class ContentCBlock
{
[Key]
public int ContentId { get; set; }
public virtual Content Content { get; set; }
[Key]
public int CBlockId { get; set; }
public virtual CBlock CBlock { get; set; }
public int DisplayOrder { get; set; }
}
and DBContext
modelBuilder.Entity<ContentCBlock>().HasKey(t => new { t.ContentId, t.CBlockId });
modelBuilder.Entity<ContentCBlock>()
.HasOne(c => c.CBlock)
.WithMany(c => c.ContentCBlocks)
.HasForeignKey(cc => cc.CBlockId);
modelBuilder.Entity<ContentCBlock>()
.HasOne(c => c.Content)
.WithMany(c => c.ContentCBlocks)
.HasForeignKey(cc => cc.ContentId);
DBSets:
public DbSet<ContentCBlock> ContentCBlocks { get; set; }
public DbSet<Content> Contents { get; set; }
public DbSet<CBlock> CBlocks { get; set; }
Everything works fine, relations, lazyLoading, ... everything.
The question is How I can sort a List of Contents by ContentCBlock.DisplayOrder
P.S.: I cannot change classes
Hope this will help you.
_context.Contents.OrderBy(c => c.ContentCBlocks.
OrderBy(c => c.DisplayOrder).Select(c => c.DisplayOrder).FirstOrDefault());

EF Core - Fluent API many-to-many self reference

I am attempting to configure 2 classes fluently.
public class Company
{
[Key]
public int Id {get; set; }
public string Name { get; set; }
public List<CompanyOwnership> OwnedBy { get; set; }
}
public class CompanyOwnership
{
public static void Configure(ModelBuilder modelBuilder)
{
modelBuilder.Entity<CompanyOwnership>()
.HasOne(cpo => cpo.OwnedCompany)
.WithMany(cp => cp.OwnedBy)
.HasForeignKey(cpo => cpo.OwnedCompanyId);
modelBuilder.Entity<CompanyOwnership>()
.HasOne(cpo => cpo.OwningCompany)
.WithMany()
.HasForeignKey(cpo => cpo.OwningCompanyId);
}
[Key]
public int Id {get; set; }
public int OwnedCompanyId { get; set; }
public Company OwnedCompany { get; set; }
public int OwningCompanyId { get; set; }
public Company OwningCompany { get; set; }
public decimal Percentage { get; set; }
}
The above code will result in an error:
InvalidOperationException: Unable to determine the relationship
represented by navigation property 'Company.OwnedBy' of type
'List<CompanyOwnership>'. Either manually configure the relationship,
or ignore this property using the '[NotMapped]' attribute or by using
'EntityTypeBuilder.Ignore' in 'OnModelCreating'.
Could I get some input about why the above setup is not enough?
Thank you,
Nvm,
it turned out that I forgot to call Configure(...).
It is working fine now.

Sitecore Glass Mapper ObjectToSwitchTo null reference in page editor

I have the following structure as Template in visual studio :
Under a page, i have one or more link root
[SitecoreType(TemplateId = "{4AAA9A10-36C2-484F-A648-2BEF349F0052}", AutoMap = true)]
public class LinkRoot : IBaseTemplate
{
[SitecoreChildren(InferType = true)]
public virtual IEnumerable<LinkItem> Children { get; set; }
[SitecoreInfo(SitecoreInfoType.TemplateId)]
public virtual Guid TemplateId { get; set; }
public Guid Id { get; set; }
public string Language { get; set; }
public ItemUri Uri { get; set; }
public int Version { get; private set; }
}
Under the link root i've LinkItems
[SitecoreType(AutoMap = true)]
public class LinkItem : IBaseTemplate
{
[SitecoreField("Link Name")]
public virtual string LinkName { get; set; }
[SitecoreField("Link")]
public virtual Link Link { get; set; }
public Guid Id { get; set; }
public string Language { get; set; }
public ItemUri Uri { get; set; }
public int Version { get; private set; }
}
I display those items in a view like that :
#foreach (var link in Model.Children.Where(o => o.TemplateId.Equals(TemplateIDs.LinksRoot.Guid)))
{
foreach (var linkChildren in link.Children)
{
using (BeginRenderLink(linkChildren, x => x.Link, isEditable: true))
{
#Editable(linkChildren, x => x.LinkName)
}
}
}
It works great, i can see my links with the good name etc, but when i go to the page editor i got this error :
Value cannot be null. Parameter name: objectToSwitchTo
at Sitecore.Diagnostics.Assert.ArgumentNotNull(Object argument, String argumentName)
at Sitecore.Common.Switcher2.Enter(TValue objectToSwitchTo)
at Sitecore.Data.Items.ContextItemSwitcher..ctor(Item item)
at Glass.Mapper.Sc.GlassHtml.MakeEditable[T](Expression1 field, Expression`1 standardOutput, T model, Object parameters, Context context, Database database, TextWriter writer)
Does someone already experienced that or have an idea why i have this error ?
Thanks
I think it means that Glass can't resolve the template of the LinkItem model.
Instead of:
[SitecoreType(AutoMap = true)]
public class LinkItem : IBaseTemplate
Try to explicitly define the template ID:
[SitecoreType(TemplateId = "{your-template-guid}", AutoMap = true)]
public class LinkItem : IBaseTemplate
I think this might be a bug, can you log it on github as an issue.

Unit test of ValidationContext is failing?

I am trying to unit test validations on a object with a base class. I am expecting 3 properties (Email,Phone and Skill>0) to fail validation, but the test is failing.
BASE CLASS
public abstract class Person : Entity
{
public string FirstName { get; set; }
public string LastName { get; set; }
public string UserName { get; set; }
public string FullName { get { return string.Format("{0} {1}", FirstName, LastName); } }
public string Email { get; set; }
public string Phone { get; set; }
public DateTime DateAdded { get; set; }
public bool Active { get; set; }
}
DERIVED CLASS
public class Contractor : Person, IValidatableObject
{
public Address Address { get; set; }
public List<Skill> SkillSet { get; set; }
public DateTime? NextAvailableDate { get; set; }
public Contractor()
{
}
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
{
if (string.IsNullOrWhiteSpace(base.FirstName))
yield return new ValidationResult("The First Name field cannot be empty.");
if (string.IsNullOrWhiteSpace(base.LastName))
yield return new ValidationResult("The Last Name field cannot be empty.");
if (string.IsNullOrWhiteSpace(base.Email))
yield return new ValidationResult("The Email field cannot be empty.");
if (string.IsNullOrWhiteSpace(base.Phone))
yield return new ValidationResult("The Phone field cannot be empty.");
if (SkillSet.Count() < 1)
yield return new ValidationResult("A contractor must have at least one skill.");
}
TEST
[TestMethod]
public void contractor_is_missing_email_phone_skill_when_created()
{
//Arrange
Contractor contractor = new Contractor { FirstName = "abc", LastName = "def" };
//Act
ValidationContext context = new ValidationContext(contractor);
IEnumerable<ValidationResult> result = contractor.Validate(new ValidationContext(contractor));
List<ValidationResult> r = new List<ValidationResult>(result);
//Assert
Assert.IsTrue(r.Count == 3);
}
Initialise your list when you create a new contractor.
public Contractor()
{
SkillSet = new List<Skill>();
}

Unable to get the correct regex pattern to change a property into a value setter

Assuming I have some object like, with LOTS of properties:
public class SomeObject
{
public SomeOtherObject1 Property1 { get; set; }
public SomeOtherObject2 Property2 { get; set; }
public SomeOtherObject3 Property3 { get; set; }
public SomeOtherObject4 Property4 { get; set; }
public SomeOtherObject5 Property5 { get; set; }
public SomeOtherObject6 Property6 { get; set; }
}
It would be really cool if I could create a constructor and copy the properties into the constructor...
public class SomeObject
{
public SomeObject
{
public SomeOtherObject1 Property1 { get; set; }
public SomeOtherObject2 Property2 { get; set; }
public SomeOtherObject3 Property3 { get; set; }
public SomeOtherObject4 Property4 { get; set; }
public SomeOtherObject5 Property5 { get; set; }
public SomeOtherObject6 Property6 { get; set; }
}
public SomeOtherObject1 Property1 { get; set; }
public SomeOtherObject2 Property2 { get; set; }
public SomeOtherObject3 Property3 { get; set; }
public SomeOtherObject4 Property4 { get; set; }
public SomeOtherObject5 Property5 { get; set; }
public SomeOtherObject6 Property6 { get; set; }
}
And use Visual Studio's Find And Replace with Regex to change the highlighted lines in the constructor from:
public SomeOtherObject1 Property1 { get; set; }
public SomeOtherObject2 Property2 { get; set; }
public SomeOtherObject3 Property3 { get; set; }
public SomeOtherObject4 Property4 { get; set; }
public SomeOtherObject5 Property5 { get; set; }
public SomeOtherObject6 Property6 { get; set; }
to:
this.Property1 = new SomeOtherObject1();
this.Property2 = new SomeOtherObject2();
this.Property3 = new SomeOtherObject3();
this.Property4 = new SomeOtherObject4();
this.Property5 = new SomeOtherObject5();
this.Property6 = new SomeOtherObject6();
First I tried:
public\s{:i}\s{:i}\s{\sget;\sset;\s}
this.\2 = new \1();
Then I thought maybe it was a line issue, so I tried:
^\s*public\s{:i}\s{:i}\s{\sget;\sset;\s}.$
this.\2 = new \1();
Anyone else have any thought on how to get this to work?
You need to escape the {} around get; set;. Also, I've used :b instead of \s and allowed for more than one. Here:
public:b+{:i}:b+{:i}:b*\{:b*get;:b*set;:b*\}
And as you wrote:
this.\2 = new \1();