Tudo o que você pode configurar com DataAnnotations também é possível com a API Fluent. O contrário não é verdade. Portanto, do ponto de vista das opções de configuração e flexibilidade, a API Fluent é "melhor".
Exemplos de configuração (com certeza, não uma lista completa) que são possíveis na API Fluent, mas não com DataAnnotations (pelo que posso ver):
Desative as exclusões em cascata:
.WillCascadeOnDelete(false)
Especifique o nome da coluna da chave estrangeira no banco de dados quando a chave não estiver exposta em seu modelo de objeto:
.Map(conf => conf.MapKey("MyForeignKeyID"))
Ajuste granular de relacionamentos, especialmente em todos os casos em que apenas um lado de uma associação é exposto no modelo de objeto:
.WithMany(...)
, WithOptional(...)
, WithRequiredDependent(...)
,WithRequiredPrincipal(...)
Especificação do mapeamento de herança entre o modelo de objeto e as tabelas do banco de dados (Tabela por Hierarquia, Tabela por Tipo, Tabela Por Classe Concreta):
.Map<TDerived>(Action<EntityMappingConfiguration<TDerived>> ...)
Editar: a Microsoft considera a API Fluent como um "recurso avançado" (cite aqui ):
A API fluente é considerada um recurso mais avançado e recomendamos o uso de anotações de dados, a menos que seus requisitos exijam o uso da API fluente.
Mas, em minha opinião, você atinge as limitações de DataAnnotations muito rapidamente (exceto, talvez, para modelos de objeto extremamente simples). Se você não puder mais ajustar seu modelo com DataAnnotations, seu último recurso é seguir as convenções de mapeamento padrão (nomeando suas propriedades de acordo com essas regras). Atualmente você não pode sobrescrever as convenções (apenas desabilitá-las; a MS anunciou para dar opções de configuração para as convenções em versões futuras do EF). Mas se você não quiser ser forçado pelas convenções de mapeamento ao definir seu modelo de objeto, sua única opção é a API Fluent.
Aprender a API Fluent é quase um must, os DataAnnotations são úteis para aplicativos simples.