16

In a EF 4.1 Code First tutorial the following code is given:

public class Department
{
    public int DepartmentId { get; set; }
    [Required]
    public string Name { get; set; }
    public virtual ICollection<Collaborator> Collaborators { get; set; }
}

Then it is explained that the fluent interface is more flexible:

Data Annotations are definitely easy to use but it is preferable to use a programmatic approach that provides much more flexibility.

The example of using the fluent interface is then given:

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<Department>().Property(dp => dp.Name).IsRequired();
    modelBuilder.Entity<Manager>().HasKey(ma => ma.ManagerCode);
    modelBuilder.Entity<Manager>().Property(ma => ma.Name)
        .IsConcurrencyToken(true)
        .IsVariableLength()
        .HasMaxLength(20);
}

I can't understand why the fluent interface is supposedly better. Is it really? From my perspective it looks like the data annotations are more clear, and have more of a clean semantic feel to it.

My question is why would a fluent interface be a better option than using attributes, especially in this case?

(Note: I'm quite new to the whole concept of fluent interfaces, so please expect no prior knowledge on this.)

Reference: http://codefirst.codeplex.com/

2
  • This question is not really about fluent interfaces. The difference is between using attributes and normal code. If the code wasn't fluent, it wouldn't change much about your question.
    – svick
    Aug 2, 2012 at 9:09
  • @svick fluent interfaces are basically normal code, but it expresses it in a different way. We moved away from specifying things in plain code to attributes, now with fluent interfaces it looks like some are backtracking and moving toward specifying things in code again. I just want to understand why you would use code instead of attributes. Do fluent interfaces warrant moving away from attributes and back to simply coding everything again?
    – Tjaart
    Aug 2, 2012 at 9:25

4 Answers 4

15

Data annotations are static, for instance this method declaration cannot change at runtime:

[MinLength(5)]
[MaxLength(20,ErrorMessage="Le nom ne peut pas avoir plus de 20 caractères")]
public new string Name { get; set; }

The fluent interface can be dynamic:

if (longNamesEnabled)
{
    modelBuilder.Entity<Manager>().Property(ma => ma.Name)
    .HasMaxLength(100);
}
else
{
    modelBuilder.Entity<Manager>().Property(ma => ma.Name)
    .HasMaxLength(20);
}

not to mention the code can be reused between properties.

7
  • 2
    why would you think that length (or any other property) of the same property would change in run-time ?
    – Yusubov
    Aug 1, 2012 at 19:22
  • 1
    @ElYusubov: I'd start with the scenarios where I didn't know the field length at coding time. Aug 1, 2012 at 19:39
  • @WyattBarnett: it may make sense to have field length as a variable only when domain parameters are fetched dynamically from some service or external un-typed source. However, dealing dynamically with domain properties would require defensive coding approach.
    – Yusubov
    Aug 1, 2012 at 19:54
  • 1
    @ElYusubov you could have two properties that need to be exactly the same except for the length so I pass them into a function that sets them up dynamically. This is why the author called them more flexible. Aug 1, 2012 at 20:26
  • 1
    @ElYusubov, you could make the field length a setting in the project settings, which feeds into the app.config or web.config. Then if a database field length changed, you could change the length in the .config file without a recompile and redeploy of the app.
    – Kyralessa
    Aug 8, 2012 at 18:54
8

I don't think that statement should be broadly applied; it is very specific to Code First. In Code First, data annotations include only a subset of the functionality that is available in the fluent API. In other words, there are certain model configurations that can only be done using the fluent API.

For example, here are some of the things that can't be specified using the annotations:

  • The precision of a DateTime property
  • The precision and scale of numeric properties
  • A String or Binary property as fixed-length
  • A String property as non-unicode
  • The on-delete behavior of relationships
  • Advanced mapping strategies

Personally, I tend to use the validation-related data annotations whenever possible since other technologies like MVC can also take advantage of these. For everything else, I prefer the fluent API.

4
  • Can you give an example of what can only be done using the fluent API? It would also be interesting to know why they have chose to do it this way. Im trying to understand fleunt APIs versus more conventional methods and entity framework is only an example. I want to know why they would prefer it over attributes. To me attributes seem more correct and readable.
    – Tjaart
    Aug 2, 2012 at 7:28
  • 1
    @Tjaart I've added some examples. While designing this, there were two main motivating principles. First, allow devs to choose. Some people view attributes as a violation of POCO, others like their declarative nature. Second, leverage existing attributes and only introduce new ones for common scenarios. You'll probably agree that the examples I gave above are relatively uncommon.
    – bricelam
    Aug 8, 2012 at 18:47
  • I did notice that OnDelete behaviour seems only to be available in the fluent API. Can you think of why they chose to do it this way? This is really what Im trying to get at with this question. The POCO violation may be a good reason if you are sharing the classes between projects. You may end up pulling in an entity framework dependency that you don't want if you use attributes!
    – Tjaart
    Aug 13, 2012 at 5:59
  • @Tjaart, I don't remember the exact reasons. I joined the team towards the end of the Code First feature and wasn't here for it's design. I'll see if I can get someone else from the team to weigh in though.
    – bricelam
    Aug 13, 2012 at 20:20
1

Answer to your question is provided in the link.

Then you define your constraints applicable to your domain within this method programmatically.

Basically, it is more or less preference to use Attributes vs programmatic approach, where programmatic approach has more control over the entity. However, there a custom way of adding Attributes to decorate your model that you may look as well.

When using this approach you may even describe relations between tables and columns. Bottom line, if you are willing to have more fine-grain control over your domain you may use this new approach that comes with EF4.1.

However, for common scenarios of validation applying Attributes should work fine because it is robust to cover most cases; and in addition it might save you time.

5
  • Can you illustrate how the programmatic way gives you more control? I'm not really getting it at this point.
    – Tjaart
    Aug 1, 2012 at 14:39
  • For example, take this " .IsConcurrencyToken(true)" - how you would do this on a Attribute definition?
    – Yusubov
    Aug 1, 2012 at 14:41
  • [ConcurrencyCheck] <- which actually seems simpler
    – Tjaart
    Aug 1, 2012 at 14:55
  • good catch, how would you then describe " relations between tables and columns" ?
    – Yusubov
    Aug 1, 2012 at 15:02
  • [ForeignKey("PersonId")] <- like so, which probably isnt as straightforward as .HasForeignKey(t => t.ProjectId), although all that is needed is to let ForeignKey() take a lambda just like the fluent interface. It still does not explain why one is better than the other.
    – Tjaart
    Aug 1, 2012 at 15:14
0

My thought is that they recommend the fluent API for code first implementations because you explicitly describe how the relationships are created in the database. If you use data annotations the database created by Entity Framework may not be what you expect. Your initial example is very simple so, like you, I would just use the data annotation method.

1
  • Can you give an example of the databse not being what you expect and how a fluent interface prevents this from happening?
    – Tjaart
    Aug 2, 2012 at 7:27

Not the answer you're looking for? Browse other questions tagged or ask your own question.