我有一个一对多的关系,即Dealer
可以拥有多个Cars
。
我尝试将我的EF C#代码转换为F#... 问题只是在我的F#代码中,它可以找到一个经销商,但是它无法获取该经销商... 它只会返回null,但在C#版本中它可以运行?
我的代码:
C#版本
public class Dealer
{
public int ID { get; set; }
public string Name { get; set; }
public virtual ICollection<Car> Cars { get; set; }
public Dealer()
{
Cars = new List<Car>();
}
}
public class Car
{
public int ID { get; set; }
public string CarName { get; set; }
public Dealer Dealer { get; set; }
public int DealerId { get; set; }
public Car()
{
Dealer = new Dealer();
}
}
public class MyContext : DbContext
{
public DbSet<Dealer> Dealers { get; set; }
public DbSet<Car> Cars { get; set; }
public MyContext()
{
Database.Connection.ConnectionString = "server=some;database=dbname;user id=uid;password=pwd";
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<Dealer>()
.HasMany(x => x.Cars)
.WithRequired(x => x.Dealer)
.HasForeignKey(x => x.DealerId);
modelBuilder.Entity<Car>()
.HasRequired(x => x.Dealer)
.WithMany()
.HasForeignKey(x => x.DealerId);
modelBuilder.Entity<Dealer>().ToTable("Dealers");
modelBuilder.Entity<Car>().ToTable("Cars");
}
}
在Program.cs中查询经销商及其汽车:
static void Main(string[] args)
{
var ctx = new MyContext();
foreach (var s in ctx.Dealers.FirstOrDefault(x => x.ID == 1).Cars)
{
Console.WriteLine(s.CarName);
}
Console.Read();
}
F#版本
type Dealer() =
let mutable id = 0
let mutable name = ""
let mutable cars = List<Car>() :> ICollection<Car>
member x.ID with get() = id and set v = id <- v
member x.Name with get() = name and set v = name <- v
abstract member Cars : ICollection<Car> with get, set
override x.Cars with get() = cars and set v = cars <- v
and Car() =
let mutable id = 0
let mutable carName = ""
let mutable dealer = Dealer()
let mutable dealerId = 0
member x.ID with get() = id and set v = id <- v
member x.CarName with get() = carName and set v = carName <- v
member x.Dealer with get() = dealer and set v = dealer <- v
member x.DealerId with get() = dealerId and set v = dealerId <- v
type MyContext() =
inherit DbContext("server=some;database=dbname;user id=uid;password=pwd")
[<DefaultValue>] val mutable dealers : DbSet<Dealer>
member x.Dealers with get() = x.dealers and set v = x.dealers <- v
[<DefaultValue>] val mutable cars : DbSet<Car>
member x.Cars with get() = x.cars and set v = x.cars <- v
override x.OnModelCreating(modelBuilder:DbModelBuilder) =
modelBuilder.Entity<Dealer>()
.HasMany(ToLinq(<@ fun ka -> ka.Cars @>))
.WithRequired(ToLinq(<@ fun sk -> sk.Dealer @>))
.HasForeignKey(ToLinq(<@ fun fg -> fg.DealerId @>)) |> ignore
modelBuilder.Entity<Car>()
.HasRequired(ToLinq(<@ fun ak -> ak.Dealer @>))
.WithMany()
.HasForeignKey(ToLinq(<@ fun ka -> ka.DealerId @>)) |> ignore
modelBuilder.Entity<Dealer>().ToTable("Dealers")
modelBuilder.Entity<Car>().ToTable("Cars")
...函数ToLinq:
let ToLinq (exp : Expr<'a -> 'b>) =
let linq = exp.ToLinqExpression()
let call = linq :?> MethodCallExpression
let lambda = call.Arguments.[0] :?> LambdaExpression
Expression.Lambda<Func<'a, 'b>>(lambda.Body, lambda.Parameters)
...并且Program.fs将获取经销商及其汽车:
let ctx = new MyContext()
let joe = ctx.Dealers.Find(1)
joe.Cars |> Seq.iter(fun x -> printfn "%s" x.CarName)
printfn "DONE"
非常感谢您的帮助!
Dealer.Cars
是一个虚拟属性,而在C#版本中它只是一个普通的属性。如果在F#中更改这个属性会有什么影响吗? - wmeyerDealer.Cars
也应该是虚拟的 - 唯一的变化就是集合现在会惰性加载,这在 c# 中也很好地实现了 (刚刚测试过)。 - ebb