How to specify the principal entity to which the foreign key refers using the Fluent API? - foreign-keys

How to specify the principal entity to which the foreign key refers using the Fluent API?
I am learning the EF Core through the tutorials over here.
I come across the following example:
public class Author
{
public int AuthorId { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public ICollection<Book> Books { get; set; }
}
public class Book
{
public int BookId { get; set; }
public string Title { get; set; }
public int AuthorFK { get; set; }
public Author Author { get; set; }
}
public class SampleContext : DbContext
{
public DbSet<Author> Authors { get; set; }
public DbSet<Book> Books { get; set; }
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Book>()
.HasForeignKey(p => p.AuthorFK);
}
}
And I can not understand how the EF Core knows that the AuthorFK refers to the Author entity. I.e. if for instance, I would like the AuthorFK to be a foreign key for an entity different from the Author entity, how could I do that?

Surprisingly, the tutorial is wrong there. The correct method is:
modelBuilder.Entity<Book>()
.HasOne(e => e.Author)
.WithMany()
.HasForeignKey(e => e.AuthorFK);
The method shown (modelBuilder.Entity<Book>().HasForeignKey) doesn't exist.
I think when you see this it'll all make sense.

Related

Sitecore item glasscast parameter value key null

I'm trying to cast a Sitecore item (its in a bucket don't know if this is relevant) to a specific type:
var sitecoreService = new SitecoreService("master");
sitecoreService.CreateType<StaffMember>(userItem);
The method Createtype casts a sitecore item to the type between the <>.
However when I execute this code I get the following error:
value cannot be null. parameter name: key
I'm trying to cast to 2 different types: User and Staffmember.
When i use above code for User it works but when I cast to Staffmember i get the error
User class:
[SitecoreType(TemplateId = "{4F6FC236-71C7-46D4-8823-09CBCDD3A233}")]
public class User
{
[SitecoreId]
public virtual Guid Id { get; set; }
[SitecoreInfo(SitecoreInfoType.Name)]
public virtual string Name { get; set; }
[SitecoreField]
public virtual string DatabaseId { get; set; }
[SitecoreField(FieldName = "Identifier")]
public virtual string Identifier { get; set; }
}
Staffmember class:
[SitecoreType(TemplateId = "{717C419F-BCDF-4DC8-8AB5-29ED672DBEC4}")]
public sealed class StaffMember
{
[SitecoreId]
public Guid Id { get; set; }
[SitecoreInfo(SitecoreInfoType.Name)]
public string Name { get; set; }
[SitecoreField]
public string DatabaseId { get; set; }
[SitecoreField(FieldName = "Identifier")]
public virtual string Identifier { get; set; }
}
Did anyone experience this error before or know how to solve it?
Thanks in advance
You may want to use this: item.GlassCast<TModel>()
http://glass.lu/Mapper/Sc/Tutorials/Tutorial9

Mapping the 'count' on child list property in AutoMapper

I am working in an ASP.NET MVC 4 application, and have something similar to this for my domain.
public class Party
{
public Cake PartyCake { get; set; }
public List<Candles> CakeCandles { get; set; }
}
I want to map that to the PartyVM which looks like so:
public class PartyVM
{
public string PartyCakeName { get; set; }
public int CandlesCount { get; set; }
}
How can I tell AutoMapper to work out the Count of the list when doing its mappings? I have this, but all this does is tell it to ignore!
Mapper.CreateMap<Party, PartyVM>()
.ForMember(dest => dest.CandlesCount, opt => opt.Ignore());
Thanks.
AutoMapper supports Count out of the box, your destination member is just named incorrectly. If you name your PartyVM property "CakeCandlesCount" it will have the right value.

Invalid column name error with EF 4.1 Code First

I've been having a problem with this for about a day now, I've searched and found similar problems with their solutions but haven't been able to fix this.
I've seen this done with the Teams example, so I'll do the same. I have a Team:
public abstract class Team
{
[Key]
public int IdTeam { get; set; }
public string Name { get; set; }
public string Description { get; set; }
}
I also have a Match object:
public class Match
{
[Key]
public int IdMatch { get; set; }
[ForeignKey("HomeTeam")]
public int IdHomeTeam { get; set; }
[ForeignKey("AwayTeam")]
public int IdAwayTeam { get; set; }
public virtual Team HomeTeam { get; set; }
public virtual Team AwayTeam { get; set; }
}
Whenever I try to access the name of either team I get an Invalid column name Team_TeamId error. I'm guessing it has something to do with EF and the Foreign Keys not being mapped correctly. I've also seen other people use ICollections, but I don't think I need them for this case.
You have to fix this in the OnModelCreating method. Entity framework can't seem to recognize the foreign keys, so you have to specify it specifically.
public class Entities : DbContext
{
...
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<Match>()
.HasRequired(b => b.AwayTeam)
.WithMany()
.HasForeignKey(b => b.IdAwayTeam);
modelBuilder.Entity<Match>()
.HasRequired(b => b.HomeTeam)
.WithMany()
.HasForeignKey(b => b.IdHomeTeam);
}
}
for more information about code first OnModelCreating check this: http://msdn.microsoft.com/en-us/library/system.data.entity.dbcontext.onmodelcreating(v=vs.103).aspx

ADO.NET Entity Framework multiple FK in one table

I'm using a code from a tutorial to try things out that I'll need in my real project. I have a table in my DataBase with a lot (16) Foreign Keys in it I have to recreate the whole DataBase using ADO.NET EF and now I'm little stuck with this particular case. Here is the code that I'm using for testing purposes:
public class Blog
{
public int BlogId { get; set; }
public string Name { get; set; }
public string Url { get; set; }
public int UserId { get; set; }
public virtual User User { get; set; }
public virtual List<Post> Posts { get; set; }
}
public class Post
{
public int PostId { get; set; }
public string Title { get; set; }
public string Content { get; set; }
//public int BlogId { get; set; }
public virtual Blog Blog { get; set; }
//public int BlogId1 { get; set; }
public virtual Blog Blog1 { get; set; }
//public int BlogId2 { get; set; }
public virtual Blog Blog2 { get; set; }
//public int BlogId3 { get; set; }
public virtual Blog Blog3 { get; set; }
//public int BlogId4 { get; set; }
public virtual Blog Blog4 { get; set; }
}
I've commented the int properties as it seems that I don't need them. Executing this code I get the following:
So there are two thing that concerns me at the moment - is this the way to add multiple Foreign Keys at one table and if so - the two rows underlined with red - why I have Blog_BlogId and Blog_BlogId1 before I get the expected Blog1_.., Blog2_...?
Ok, I lost the post here from where I got the solution but in this particular case it seems to be some sort of naming convention I have to uncomment the commented code and change the names without using numbers or underscore. Then in OnModelCreating event add this code as many times as I need :
modelBuilder.Entity<Post>().HasRequired(c => c.Blog)
.WithMany(m => m.Posts)
.HasForeignKey(c => c.BlogId)
.WillCascadeOnDelete();
modelBuilder.Entity<Post>().HasRequired(c => c.Blogged)
.WithMany()
.HasForeignKey(c => c.BloggedId)
.WillCascadeOnDelete(false);
Notice that I change the property name and the class instance name every time I add new record for foreign key.

WCF DataContract With List of RegExs Won't Serialize Properly

I have a class that looks something like this:
[DataContract]
public class InboundMailbox
{
public const char EmailSeparator = ';';
[DataMember]
public string POP3Host { get; set; }
[DataMember]
public string EmailId { get; set; }
[DataMember]
public string WebServiceURL { get; set; }
[DataMember]
public List<Regex> Allowed { get; set; }
[DataMember]
public List<Regex> Disallowed { get; set; }
}
If Allowed and Disallowed are empty then it serializes just fine across my WCF service. As soon as one of those lists contains a value, I get this in a CommunicationException:
The socket connection was aborted. This could be caused by an error
processing your message or a receive timeout being exceeded by the
remote host, or an underlying network resource issue. Local socket
timeout was '00:00:29.9899990'.
Why is it giving me a hard time about serializing those two properties? Thanks in advance.
The Regex class implements the ISerializable interface, which means that it's serialized as a property bag (dictionary of string/object). Looking at the implementation of ISerializable.GetObjectData for the Regex class in Reflector, it shows that it serializes both the pattern (string) and the options (of type RegexOptions). Since the type is ISerializable, WCF doesn't know about RegexOptions, so it will fail to serialize this type.
One simple solution is to simply "tell" WCF that this is a known type, so the serialization will work (an easy place to declare it is using the [KnownType] attribute in the InboundMailbox class (see below). Another option would be to have the data member as the regex pattern instead of the Regex itself (and possibly the options as well).
public class StackOverflow_7909261
{
[DataContract]
[KnownType(typeof(RegexOptions))]
public class InboundMailbox
{
public const char EmailSeparator = ';';
[DataMember]
public string POP3Host { get; set; }
[DataMember]
public string EmailId { get; set; }
[DataMember]
public string WebServiceURL { get; set; }
[DataMember]
public List<Regex> Allowed { get; set; }
[DataMember]
public List<Regex> Disallowed { get; set; }
}
public static void Test()
{
MemoryStream ms = new MemoryStream();
InboundMailbox obj = new InboundMailbox
{
POP3Host = "popHost",
EmailId = "email",
WebServiceURL = "http://web.service",
Allowed = new List<Regex>
{
new Regex("abcdef", RegexOptions.IgnoreCase),
},
Disallowed = null,
};
DataContractSerializer dcs = new DataContractSerializer(typeof(InboundMailbox));
try
{
dcs.WriteObject(ms, obj);
Console.WriteLine(Encoding.UTF8.GetString(ms.ToArray()));
}
catch (Exception ex)
{
Console.WriteLine(ex);
}
}
}
BTW, you'd find out the error if you had enabled tracing on the server side; it would have an exception saying that the type RegexOptions wasn't expected.